• 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 in boost/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 in boost/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 in boost/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 进程锁相关推荐

  1. 分布式锁,进程锁,线程锁到底是什么

    在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁:大家都不陌生,主要用来给方法.代码块加锁.当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一 ...

  2. 一句话说清分布式锁,进程锁,线程锁

    一句话说清分布式锁,进程锁,线程锁 在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁,进程锁,分布式锁 线程锁:大家都不陌生,主要用来给方法.代码块 ...

  3. 并发 --- 31 进程锁 守护进程 进程队列

    一.进程的其他方法 1.   .name      进程名   (可指定) 2.  .pid     进程号 3.   os.getpid         在什么位置就是什么的进程号 4.   .is ...

  4. day 31 进程的其他方法 进程锁 进程队列

    一.进程的其他方法 1.   .name      进程名   (可指定) 2.  .pid     进程号 3.   os.getpid         在什么位置就是什么的进程号 4.   .is ...

  5. 进程锁 读写文件的小例子 C++代码

    代码 #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sy ...

  6. 正在等待缓存锁:无法获得锁_一句话说清分布式锁,进程锁,线程锁

    推荐阅读 1. Java 性能优化:教你提高代码运行的效率 2. Java问题排查工具清单 3. 记住:永远不要在MySQL中使用UTF-8 4. Springboot启动原理解析 在分布式集群系统的 ...

  7. 进程锁、事件、进程队列、进程间共享数据、生产者消费者模型

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 进程锁(Lock) 锁的基本概念 锁的基本用法 模拟12306抢票软件 信号量:Semaphone 概念 Semaphore ...

  8. 多进程中的进程锁(互斥锁)

    多进程中遇到的问题 以下实例中: import threading lock = threading.Lock() num = 0 def work1(asd):global numfor i in ...

  9. python守护进程去中断子进程_04 Python并发编程(守护进程,进程锁,进程队列)

    进程的其他方法 P = Process(target=f,) P.Pid 查看进程号  查看进程的名字p.name P.is_alive()  返回一个true或者False P.terminate( ...

最新文章

  1. apache php mysql配置详解,详细介绍:Apache+PHP+MySQL配置攻略_php基础
  2. java integer常量池_为什么Integer常量池的行为在127发生变化?
  3. 受损虚拟机的修复方法
  4. pcl之将QVTKWidget添加到QtCreator
  5. vSphere Replication:虚拟机的保护伞
  6. SliderBar4.0常用滑块滚动效果封装
  7. 华为智能体发布,智能联接火了
  8. 频谱分析中的频谱泄露现象(以ADC性能测试场景为例)
  9. Java贪吃蛇(附完整代码下载链接)-跟随狂神一天完成
  10. [附源码]Python计算机毕业设计SSM建筑工程管理系统(程序+LW)
  11. 值得你收藏的Notes应用模板
  12. 每日力扣——95. 提莫攻击
  13. vue-router有哪几种导航钩子?(具体怎么用的)
  14. openwrt ipv6 防火墙设置
  15. 从开源Sakai出发 构建国内远程教育系统
  16. 基于神经网络的自适应最优控制
  17. [转]【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
  18. Elasticsearch学习心得及常见问题
  19. 计算机主机接口有哪些,计算机接口有哪些
  20. 光宇游戏软件测试面试,新闻中心

热门文章

  1. grpc入门到精通_Spring Cloud 从入门到精通(一)Nacos 服务中心初探
  2. linux串口编程实例_Linux 网络编程——原始套接字实例:发送 UDP 数据包
  3. bi 存储过程方案_BI 系统中容易被忽视的数据源功能
  4. Qt事件传递相关问题
  5. Spark-三大数据结构之-广播变量
  6. Mybatis四种分页方式
  7. CCIE-LAB-第十二篇-EIGRP+EIGRP末节区域+leak map+分发列表
  8. 【机器学习】 - keras中的模型可视化plot_model模块(含依赖包pydot和graphviz的详细安装过程与注意事项)
  9. 【PAT - 甲级1020】Tree Traversals (25分)(树的遍历,给定中序后序,求层次遍历)
  10. 【牛客 - 330F】Applese 的QQ群(拓扑排序,二分)