同时锁定两个互斥对象
Lock two mutex at same time
我正在尝试实现一个多入多出的线程间通道类。我有三个互斥对象:当缓冲区已满时,full
锁定。empty
在缓冲区为空时锁定。当其他人正在修改缓冲区时,th
会锁定。我的单个IO程序看起来像
operator<<(...){
full.lock() // locks when trying to push to full buffer
full.unlock() // either it's locked or not, unlock it
th.lock()
...
empty.unlock() // it won't be empty
if(...)full.lock() // it might be full
th.unlock()
operator>>(...){
// symmetric
}
这对于单个IO来说完全可以。但对于多个IO,当使用者线程解锁full
时,所有提供者线程都将关闭,只有一个线程将获得th
,缓冲区可能会因为该单个线程而再次满,而不再进行完全检查。当然,我可以再添加一个full.lock()
,但这是无穷无尽的。有没有办法同时锁定full
和th
?我确实看到了类似的问题,但我不认为秩序是问题所在。
是的,使用std::lock(full , th);
,这可以避免的一些死锁
例如:线程1:
full.lock();
th.lock();
线程2:
th.lock();
full.lock();
这可能会导致死锁,但以下情况不会:
线程1:
std::lock(full, th);
线程2:
std::lock(th, full);
不,不能原子锁定两个互斥对象。
此外,看起来您在一个线程中锁定互斥对象,然后在另一个线程中将其解锁。这是不允许的。
对于这个问题,我建议切换到条件变量。请注意,将一个互斥对象与多个条件变量关联起来是完全可以的。
不,您不能同时锁定两个互斥体,但您可以为等待的线程使用std::condition_variable
,并在完成后调用notify_one
请参阅此处了解更多详细信息。
您试图实现的功能需要类似于System V信号量的东西,其中可以原子地应用信号量上的一组操作。在你的情况下,你会有3个信号量:
- 信号量1-锁定,初始化为0
- 信号量2-可用数据的计数器,初始化为0
- 信号量3-可用缓冲区的计数器,初始化您有多少缓冲区
则推送操作将执行此组锁定:
- 检查信号量1为0
- 将信号量1增加+1
- 将信号量2增加+1
- 将信号量3减少-1
然后
- 将信号量1减少-1
解锁。则要提取数据,第一组将更改为:
- 检查信号量1为0
- 将信号量1增加+1
- 将信号量2减少-1
- 将信号量3增加+1
解锁与以前相同。使用互斥锁,这是一种特殊情况下的信号量,很可能不会以这种方式解决您的问题。首先,它们是二进制的,即只有2个状态,但更重要的是API不提供对它们的组操作。因此,您可以为您的平台找到信号量实现,或者使用带有条件变量的单个互斥体来向等待的线程发出数据或缓冲区可用的信号。
- 如何返回一个类的两个对象相加的结果
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 为什么C++在将一个对象复制到另一个对象时需要对这两个对象进行低级常量限定
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 如何在Qt中连接来自不同窗口的两个对象?
- C++两个对象,其中包含指向同一数组不同部分的指针
- 为什么将两个对象分配给另一个对象后,两个对象不一样?
- C++:在另外两个对象之间共享一个对象
- 在单元测试中,如何在不使用 operator== 的情况下比较两个对象,这可能会错过新成员?
- 同一类的两个对象相互引用
- 将类对象传递给两个对象
- 如何调用运算符函数添加两个对象?
- 让一个名为A的类.传递以下两个对象有什么区别:(a)obj1和(b)obj1()
- 比较矢量迭代中的两个对象C
- 当我有两个对象时<<如何重载运算符?(有关系)
- 声明一个模板函数,将模板类友元的两个对象(仅)带到这两个专用化
- 使用指针将两个对象(每个都与一个类)相关联
- 比较类的两个对象之间的数据