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 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 获取屏幕宽度和高度的几种方法

方法一&#xff1a; public static void getScreenSize1(Context context){WindowManager windowManager (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display defaultDisplay windowManager.getDefaultDisplay();Point point new Point();defaultD…

毛概 第二章新民主主义革命理论

1.新民主主义革命的总路线 2.

解决undefined reference to symbol ‘sem_close@@GLIBC_2.2.5‘问题

错误图示 问题原因 编译的时候&#xff0c;没有引入库文件 sem()位于pthread库中&#xff0c;所以在编译和链接时请确保使用-pthread标志&#xff0c;因此在编译的时候需要导入pthread库文件编译的顺序出现问题 解决办法 在clion的CMakeLists.txt文件中添加这一行代码set(CM…

Android 在onCreate()方法中获取控件宽高值为0解决方案

大家很多时候需要在Activity或者Fragment的onCreate()方法中获取声明的空间的高度或者宽度&#xff0c;进行位置移动或者其他操作&#xff0c;但是当调用 view.getHeight() 或者 view.getWidth() 获取的竟然为0。。。 其实很容易理解&#xff0c;在onCreate()的时候&#xff0…

C++运算符与类型转换

除法/ 参与运算时,结果符号按照(为,–为,-或为-),两个都是整型结果直接去除小数部分 -3/1-1 -3/-13 3/-13 除法 一律向0取整&#xff08;即直接切除小数部分&#xff09;。 取余% 参与运算为整型,结果符号和第一个相同(当结果不为0时) /* 21%63 -21%6-3 -21%-6-3 参与取余的运…

使用named_mutex实现锁机制

介绍 named_mutex是一个进程锁&#xff0c;考虑到进程和线程之间的区别区别&#xff1a;一个工作单元要想被称作进程&#xff0c;它必须要有操作系统指派给他的地址空间&#xff0c;必须拥有进程ID&#xff0c;必须拥有状态和进程表中的表项。进程和线程之间最大的区别是进程有…

Android Studio 突然出现很多红色波浪线或红色感叹号解决方案

最近在开发过程中&#xff0c;某次打开Android工程之后&#xff0c;代码了出现大量的红色波浪线报错提示&#xff0c;但是工程确可以正常编译、正常打包&#xff0c;尝试了很多方法都无法去掉&#xff0c;最后找到了最有效的解决方案&#xff0c;步骤如下&#xff1a; 1、删掉…

安卓常用布局学习

线性布局 布局方向 水平 android:orientation“horizontal” 垂直android:orientation“vertical” gravity对齐方式–center 布局权重:视图中剩余部分的面积所占比例 android:layout_weight“1”(数字) 水平布局:android:layout_width“0dp” 垂直布局:android:layout_heigh…

Android Canvas绘制带箭头的直线

先看下效果图&#xff1a; 下面我们直接看代码 我自定义了一个View&#xff0c;代码如下&#xff1a; package com.davis.drawtrangle;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; imp…

使用named_mutex实现读写锁,实现进程之间读共享写独占

代码 代码的名称是read_write_mutex.h这个代码可用&#xff0c;但是未优化&#xff0c;还存在冗余的代码如果涉及到进程挂掉了&#xff0c;造成进程堵塞&#xff0c;如何解决&#xff1f;还未涉及 //#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP #define BOOST_THREAD_PTHR…

Android Activity之间传递类对象

一、简介 开发过程中&#xff0c;Activity之间传递数据是必不可少的&#xff0c;Android中使用Intent和Bundle作为数据载体&#xff0c;在Activity之间传递&#xff0c;对于基础数据类型&#xff0c;Bundle已经提供了相关的put、set方法&#xff0c;而作为自定义的类型则需要有…

C++3个汉诺塔递归问题

3个汉诺塔问题A—>C 移动次数2^n-1 hannoni(int n,char a,char b,char c)把n个盘子借助b,从a移动到cmove(int n,char a,char c)把第n个盘子,从a移动到c #include<iostream> #include<cmath> using namespace std; //汉诺塔问题A--->C //2^n-1次移动次数 …

clion编译器解决undefined reference to symbol ‘shm_open@@GLIBC_2.2.5‘

修改CMakelists文件 cmake_minimum_required(VERSION 3.17) project(mutex_learn)set(CMAKE_CXX_STANDARD 14)set(BOOST_ROOT "/usr/local/include/boost") #添加头文件搜索路径 include_directories(/usr/local/include) #添加库文件搜索路径 link_directories(/us…

Android 拦截或屏蔽返回键

在Android开发中我们常常会遇到需要拦截或屏蔽返回键的需求&#xff0c;对拦截后的返回键进行特殊操作。 监听返回键有两种方式 1、重写OnBackPressed方法 Overridepublic void onBackPressed() {// 完全由自己控制返回键逻辑&#xff0c;系统不再控制&#xff0c;但是有个前…

C++递归斐波那契数列

第一种 //斐波那契数列 // 0 1 1 … //从第1个开始 代码 #include<iostream> #include<cmath> using namespace std; //斐波那契数列 // 0 1 1 ... //从第1个开始 int f(int n) {int m; if(n1)return 0;if(n2)return 1;elsemf(n-1)f(n-2);return m;} int mai…

Android onActivityResult中requestCode与resultCode区别

想要了解requestCode与resultCode的区别&#xff0c;我们需要先了解以下三个方法的用法&#xff1a; startActivityForResult(Intent intent, Int requestCode) setResut(int resultCode, Intent intent) onActivityResult(int requestCode, int resultCode, Intent intent) …

使用named_mutex和named_condition配合实现读写锁

代码 代码的名称是read_write_mutex.h初步优化如果涉及到进程挂掉了&#xff0c;造成进程堵塞&#xff0c;如何解决&#xff1f;还未涉及 #include <boost/interprocess/sync/named_condition.hpp> #include <boost/interprocess/sync/named_mutex.hpp>namespace …

C++的输入与输出

输入与输出 输入:从外部输入设备(键盘)向计算机输入数据 输出:从计算机向外部输出设备(显示屏)输出数据 C使用流对象实现 使用流对象cin与cout,将标准输入输出流库的头文件iostream包含到源文件 #include<iostream>//标准输入输出库 using namespace std;//使用标准命…

Android 动态计算ListView的高度

目录一、简介二、效果图三、代码实现一、简介 在Android开发的过程中有的时候我们需要手动计算ListView的高度&#xff0c;比如说&#xff0c;ScrollView中嵌套ListView的时候&#xff0c;我们就需要手动精确计算ListView的高度了。 如果ListView的Item高度是固定的话还好计算…

DjangoRestFramework(drf实现五个接口)

安装&#xff1a;pip install djangorestframework 在使用drf之前&#xff0c;先 使用原生Django实现5个接口 models.py from django.db import modelsclass Book(models.Model):namemodels.CharField(max_length53)pricemodels.IntegerField() views.py from app01 impor…