条件变量死锁 [英] Condition variable deadlock

查看:98
本文介绍了条件变量死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码中存在与使用条件变量有关的死锁问题.这更多的是设计问题,而不是纯粹的代码问题.了解正确的设计后,我便可以真正编写代码了.我有以下情况:

  1. 线程A等待条件变量.
  2. 线程B调用notify_all,线程A醒来.

这当然是我想发生的事情,并且当一切都按预期工作时会发生什么.但是有时候,我得到的是以下情况:

  1. 线程A在开始等待条件变量之前立即执行代码.
  2. 线程B调用notify_all,认为线程A正在等待.
  3. 线程A开始等待条件变量,但没有意识到线程B已经告诉它停止等待.死锁.

解决此问题的最佳方法是什么?我想不出一种可靠的方法来检查线程A是否实际上正在等待,以便知道何时应在线程B中调用notify_all.我是否必须求助于timed_lock?我讨厌.

解决方案

在线程A等待条件变量之前的一段时间内,它必须持有互斥量.最简单的解决方案是确保线程B在调用notify_all时保持相同的互斥量.像这样:

std::mutex m;
std::condition_variable cv;
int the_condition = 0;

Thread A: {
  std::unique_lock<std::mutex> lock(m);
  do something
  while (the_condition == 0) {
    cv.wait(lock);
  }
  now the_condition != 0 and thread A has the mutex
  do something else
} // releases the mutex;

Thread B: {
  std::unique_lock<std::mutex> lock(m);
  do something that makes the_condition != 0
  cv.notify_all();
} // releases the mutex

这保证了线程B仅在线程A获取互斥量之前或在线程A等待条件变量时才执行notify_all().

不过,这里的另一个关键是while循环,等待the_condition变为true.一旦A具有互斥量,在A测试了_condition,发现其为false并开始等待(从而释放互斥量)之前,其他任何线程都不可能更改_condition.

重点是:您真正在等待的是the_condition的值变为非零,std :: condition_variable :: notify_all只是告诉您线程B认为线程A应该唤醒并重新测试. /p>

I have a problem with a deadlock in my code related to the use of condition variables. This is more of a design question than a pure code question. I have no problem actually writing code once I understand the correct design. I have the following scenario:

  1. Thread A waits on a condition variable.
  2. Thread B calls notify_all, and thread A wakes up.

This is of course what I want to happen, and is what does happen when everything works as expected. But sometimes, I get the following scenario instead:

  1. Thread A executes the code right before it begins to wait on the condition variable.
  2. Thread B calls notify_all, thinking that thread A is waiting.
  3. Thread A begins waiting on the condition variable, not realizing that thread B already told it to stop waiting. Deadlock.

What is the best way to resolve this? I can't think of a reliable way to check whether thread A is actually waiting, in order to know when I should call notify_all in thread B. Do I have to resort to timed_lock? I would hate to.

解决方案

During the period just before Thread A waits on condition variable it must be holding a mutex. The easiest solution is to make sure that Thread B is holding the same mutex at the time it calls notify_all. So something like this:

std::mutex m;
std::condition_variable cv;
int the_condition = 0;

Thread A: {
  std::unique_lock<std::mutex> lock(m);
  do something
  while (the_condition == 0) {
    cv.wait(lock);
  }
  now the_condition != 0 and thread A has the mutex
  do something else
} // releases the mutex;

Thread B: {
  std::unique_lock<std::mutex> lock(m);
  do something that makes the_condition != 0
  cv.notify_all();
} // releases the mutex

This guarantees that Thread B only does the notify_all() either before Thread A acquires the mutex or while Thread A is waiting on the condition variable.

The other key here, though, is the while loop waiting for the_condition to become true. Once A has the mutex it should not be possible for any other thread to change the_condition until A has tested the_condition, found it false, and started waiting (thus releasing the mutex).

The point is: what you are really waiting for is for the value of the_condition to become non-zero, the std::condition_variable::notify_all is just telling you that thread B thinks thread A should wake up and retest.

这篇关于条件变量死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆