Synchronization 进程锁
- Boost.Interprocess允许多个进程同时使用共享内存。因为共享内存从定义上来说是进程间共享的,所以Boost.Interprocess需要支持某种同步。
- 想到同步,我们会想到C++11标准库中的类或Boost.Thread。但是这些类只能用来同步同一进程内的线程,它们不支持不同进程的同步。不过,由于两种情况下面临的挑战是一样的,所以概念也是一样的。
- 在多线程应用程序中,同步对象(如mutexes和条件变量)驻留在同一个地址空间中,因此所有线程都可以使用,而共享内存的挑战是,独立的进程需要共享这些对象。例如,如果一个进程创建了一个mutex,那么它就需要以某种方式从另一个进程中访问。
- Boost.Interprocess提供了两种同步对象:匿名对象直接存储在共享内存中,这使得它们对所有进程自动可用。命名对象由操作系统管理,不存储在共享内存中,可以通过名称从程序中引用(named_mutex)。
Example 33.12. Using a named mutex with boost::interprocess::named_mutex
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <iostream>using namespace boost::interprocess;int main()
{managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")();named_mutex named_mtx{open_or_create, "mtx"};named_mtx.lock();++(*i);std::cout << *i << '\n';named_mtx.unlock();
}
- Example 33.12 creates and uses a named mutex using the class
boost::interprocess::named_mutex
, which is defined inboost/interprocess/sync/named_mutex.hpp
. - boost::interprocess::named_mutex的构造函数期望得到一个参数,指定是否应该创建或打开mutex,以及mutex的名称。每个知道这个名字的进程都可以打开同一个mutex。要访问共享内存中的数据,程序需要通过调用成员函数lock()来获得mutex的所有权。由于mutexes一次只能由一个进程拥有,所以另一个进程可能需要等待,直到mutex被unlock()释放。一旦一个进程拥有了一个mutex的所有权,它就拥有了对mutex所保护的资源的独占性访问权。在示例33.12中,资源是一个类型为int的变量,它被递增并写入标准输出流。
- 如果示例程序被多次启动,每个实例都会打印一个比前一个值递增1的值。由于有了mutex,不同进程之间对共享内存和变量本身的访问是同步的。
Example 33.13. Using an anonymous mutex with interprocess_mutex
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <iostream>using namespace boost::interprocess;int main()
{managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")();interprocess_mutex *mtx =managed_shm.find_or_construct<interprocess_mutex>("mtx")();mtx->lock();++(*i);std::cout << *i << '\n';mtx->unlock();
}
- Example 33.13 uses an anonymous mutex of type
boost::interprocess::interprocess_mutex
, which is defined inboost/interprocess/sync/interprocess_mutex.hpp
. In order for the mutex to be accessible for all processes, it is stored in the shared memory. 例33.13的行为与前一个完全相同。唯一不同的是mutex,它现在直接存储在共享内存中。这可以通过类 boost::interprocess::managed_shared_memory 中的成员函数 construct() 或 find_or_construct() 来实现。除了lock(),boost::interprocess::named_mutex和boost::interprocess::interprocess_mutex都提供了成员函数try_lock()和timed_lock()。它们的行为与标准库和Boost.Thread中的对应函数完全相同。如果需要递归互斥,Boost.Interprocess提供了两个类:boost::interprocess::named_recursive_mutex和boost::interprocess::interprocess_recursive_mutex。
互斥保证了对共享资源的独占访问,而条件变量则控制了谁在什么时候拥有独占访问权。一般来说,Boost.Interprocess提供的条件变量与C++11标准库和Boost.Thread提供的条件变量的工作原理类似。它们具有类似的接口,这使得这些库的用户在Boost.Interprocess中使用这些变量时,会立即感到宾至如归。
Example 33.14. Using a named condition with boost::interprocess::named_condition
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <iostream>using namespace boost::interprocess;int main()
{managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")(0);named_mutex named_mtx{open_or_create, "mtx"};named_condition named_cnd{open_or_create, "cnd"};scoped_lock<named_mutex> lock{named_mtx};while (*i < 10){if (*i % 2 == 0){++(*i);named_cnd.notify_all();named_cnd.wait(lock);}else{std::cout << *i << std::endl;++(*i);named_cnd.notify_all();named_cnd.wait(lock);}}named_cnd.notify_all();shared_memory_object::remove("shm");named_mutex::remove("mtx");named_condition::remove("cnd");
}
- Example 33.14 uses a condition variable of type
boost::interprocess::named_condition
, which is defined inboost/interprocess/sync/named_condition.hpp
. Because it is a named variable, it does not need to be stored in shared memory. - 例33.14使用了一个类型为boost::interprocess::named_condition的条件变量,它定义在boost/interprocess/sync/named_condition.hpp中。因为它是一个命名变量,所以不需要存储在共享内存中。
- 应用程序使用一个 while 循环来递增一个类型为 int 的变量,该变量存储在共享内存中。虽然变量随着循环的每次迭代而递增,但它只会在每第二次迭代时被写入标准输出流--只写奇数。每当变量递增1时,条件变量命名为_cnd的成员函数wait()被调用。一个锁--在例33.14中,名为锁的变量--被传递给这个成员函数。这是基于RAII的习惯,即在构造函数中取得一个mutex的所有权,并在destructor中释放它。
- 这个锁是在while循环之前创建的,并且在整个程序执行过程中拥有mutex的所有权。然而,如果将其作为参数传递给wait(),锁就会自动释放。条件变量用于等待指示等待结束的信号。同步是由成员函数wait()和notify_all()控制的。当程序调用wait()时,相应的mutex的所有权被释放。然后,程序会一直等待,直到对同一个条件变量调用notify_all()。启动时,例33.14似乎并没有什么作用。在while循环内将变量i从0增到1后,程序通过调用wait()等待信号。为了发射信号,需要启动第二个程序实例。
- 第二个实例在进入 while 循环之前,试图取得同一个 mutex 的所有权。由于第一个实例通过调用wait()释放了mutex,所以成功了。因为变量已经被递增了一次,第二个实例执行if表达式的else分支,并将当前值写入标准输出流。然后将值递增1。现在第二个实例也调用wait()。然而,在这之前,它调用notify_all(),这确保了两个实例的正确合作。第一个实例得到通知,并试图再次获得mutex的所有权,而这个mutex仍然由第二个实例拥有。然而,由于第二个实例在调用notify_all()后立即调用wait(),它会自动释放所有权,所以第一个实例将在此时获得所有权。两个实例交替进行,递增共享内存中的变量。但是,只有一个实例将值写入标准输出流。当变量达到值10时,while循环就结束了。为了避免让另一个实例永远等待信号,循环结束后再调用一次notify_all()。在终止之前,共享内存、mutex和条件变量被销毁。
- 就像有两种类型的mutexes--一种是必须存储在共享内存中的匿名类型,另一种是命名类型--条件变量也有两种类型。例33.15是使用匿名条件变量重写的上一个例子。
Example 33.15. Using an anonymous condition with interprocess_condition
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <iostream>using namespace boost::interprocess;int main()
{managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")(0);interprocess_mutex *mtx =managed_shm.find_or_construct<interprocess_mutex>("mtx")();interprocess_condition *cnd =managed_shm.find_or_construct<interprocess_condition>("cnd")();scoped_lock<interprocess_mutex> lock{*mtx};while (*i < 10){if (*i % 2 == 0){++(*i);cnd->notify_all();cnd->wait(lock);}else{std::cout << *i << std::endl;++(*i);cnd->notify_all();cnd->wait(lock);}}cnd->notify_all();shared_memory_object::remove("shm");
}
- 例33.15的工作原理和上一个完全一样,同样需要启动两次才能将int变量递增十次。除了mutexes和条件变量,Boost.Interprocess还支持semaphores和文件锁。Semaphores与条件变量类似,只是它们不区分两种状态,而是基于一个计数器。文件锁的行为类似于mutexes,只是它们用于硬盘上的文件,而不是内存中的对象。
- 就像C++11标准库和Boost.Thread区分不同类型的mutexes和锁一样,Boost.Interprocess提供了几种mutexes和锁。例如,mutexes可以是独占的,也可以是非独占的。如果多个进程需要同时读取数据,这很有帮助,因为只需要一个独占的互斥来写入数据。不同的锁类可以将RAII习语应用于单个mutexes。
- 除非使用匿名同步对象,否则名称应该是唯一的。即使mutexes和条件变量是基于不同类的对象,但对于由Boost.Interprocess封装的操作系统依赖性接口来说,这不一定成立。在Windows上,mutexes和条件变量都使用相同的操作系统函数。如果两个对象使用相同的名称,每种类型的对象都有一个,那么程序在Windows上将无法正常运行。
参考链接
- Synchronization
Synchronization 进程锁相关推荐
- 分布式锁,进程锁,线程锁到底是什么
在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁:大家都不陌生,主要用来给方法.代码块加锁.当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一 ...
- 一句话说清分布式锁,进程锁,线程锁
一句话说清分布式锁,进程锁,线程锁 在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁,进程锁,分布式锁 线程锁:大家都不陌生,主要用来给方法.代码块 ...
- 并发 --- 31 进程锁 守护进程 进程队列
一.进程的其他方法 1. .name 进程名 (可指定) 2. .pid 进程号 3. os.getpid 在什么位置就是什么的进程号 4. .is ...
- day 31 进程的其他方法 进程锁 进程队列
一.进程的其他方法 1. .name 进程名 (可指定) 2. .pid 进程号 3. os.getpid 在什么位置就是什么的进程号 4. .is ...
- 进程锁 读写文件的小例子 C++代码
代码 #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sy ...
- 正在等待缓存锁:无法获得锁_一句话说清分布式锁,进程锁,线程锁
推荐阅读 1. Java 性能优化:教你提高代码运行的效率 2. Java问题排查工具清单 3. 记住:永远不要在MySQL中使用UTF-8 4. Springboot启动原理解析 在分布式集群系统的 ...
- 进程锁、事件、进程队列、进程间共享数据、生产者消费者模型
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 进程锁(Lock) 锁的基本概念 锁的基本用法 模拟12306抢票软件 信号量:Semaphone 概念 Semaphore ...
- 多进程中的进程锁(互斥锁)
多进程中遇到的问题 以下实例中: import threading lock = threading.Lock() num = 0 def work1(asd):global numfor i in ...
- python守护进程去中断子进程_04 Python并发编程(守护进程,进程锁,进程队列)
进程的其他方法 P = Process(target=f,) P.Pid 查看进程号 查看进程的名字p.name P.is_alive() 返回一个true或者False P.terminate( ...
最新文章
- apache php mysql配置详解,详细介绍:Apache+PHP+MySQL配置攻略_php基础
- java integer常量池_为什么Integer常量池的行为在127发生变化?
- 受损虚拟机的修复方法
- pcl之将QVTKWidget添加到QtCreator
- vSphere Replication:虚拟机的保护伞
- SliderBar4.0常用滑块滚动效果封装
- 华为智能体发布,智能联接火了
- 频谱分析中的频谱泄露现象(以ADC性能测试场景为例)
- Java贪吃蛇(附完整代码下载链接)-跟随狂神一天完成
- [附源码]Python计算机毕业设计SSM建筑工程管理系统(程序+LW)
- 值得你收藏的Notes应用模板
- 每日力扣——95. 提莫攻击
- vue-router有哪几种导航钩子?(具体怎么用的)
- openwrt ipv6 防火墙设置
- 从开源Sakai出发 构建国内远程教育系统
- 基于神经网络的自适应最优控制
- [转]【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
- Elasticsearch学习心得及常见问题
- 计算机主机接口有哪些,计算机接口有哪些
- 光宇游戏软件测试面试,新闻中心
热门文章
- grpc入门到精通_Spring Cloud 从入门到精通(一)Nacos 服务中心初探
- linux串口编程实例_Linux 网络编程——原始套接字实例:发送 UDP 数据包
- bi 存储过程方案_BI 系统中容易被忽视的数据源功能
- Qt事件传递相关问题
- Spark-三大数据结构之-广播变量
- Mybatis四种分页方式
- CCIE-LAB-第十二篇-EIGRP+EIGRP末节区域+leak map+分发列表
- 【机器学习】 - keras中的模型可视化plot_model模块(含依赖包pydot和graphviz的详细安装过程与注意事项)
- 【PAT - 甲级1020】Tree Traversals (25分)(树的遍历,给定中序后序,求层次遍历)
- 【牛客 - 330F】Applese 的QQ群(拓扑排序,二分)