我试图实现多入多出的线程间通道类。我有三个互斥锁: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
吗?我确实看到了类似的问题,但我不知道订单是问题所在。
答案 0 :(得分:3)
是的,使用std::lock(full , th);
,这可以避免一些死锁
例如: 线程1:
full.lock();
th.lock();
线程2:
th.lock();
full.lock();
这可能会造成僵局,但以下内容不会:
线程1:
std::lock(full, th);
线程2:
std::lock(th, full);
答案 1 :(得分:2)
不,你不能自动锁定两个互斥锁。
此外,您看起来像是在一个线程中锁定互斥锁,然后在另一个线程中解锁它。这是不允许的。
我建议切换到此问题的条件变量。请注意,将一个互斥锁与多个条件变量相关联是完全没问题的。
答案 2 :(得分:0)
不,你不能一次锁定两个互斥锁,但是你可以使用std::condition_variable
作为等待线程,并在完成后调用notify_one
。
有关详细信息,请参阅here。
答案 3 :(得分:-1)
您尝试实现的功能将需要类似于System V信号量的内容,其中信号量上的操作组可以原子应用。在你的情况下,你将有3个信号量:
然后推送操作会将此组锁定:
然后
解锁。然后拉数据第一组将改为:
解锁与以前一样。使用特殊情况信号量的互斥量很可能不会以这种方式解决您的问题。首先它们是二进制的,即只有2个状态,但更重要的API不提供对它们的组操作。因此,您要么为您的平台找到信号量实现,要么使用带有条件变量的单个互斥锁来通知等待线程数据或缓冲区可用。