同时锁定两个互斥锁

时间:2017-01-18 17:52:59

标签: c++ multithreading mutex

我试图实现多入多出的线程间通道类。我有三个互斥锁: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(),但这是无穷无尽的。无论如何要同时锁定fullth吗?我确实看到了类似的问题,但我不知道订单是问题所在。

4 个答案:

答案 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个信号量:

  • 信号量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不提供对它们的组操作。因此,您要么为您的平台找到信号量实现,要么使用带有条件变量的单个互斥锁来通知等待线程数据或缓冲区可用。