条件变量信号
Posted
技术标签:
【中文标题】条件变量信号【英文标题】:condition variables signaling 【发布时间】:2012-12-08 08:19:12 【问题描述】:在此链接here 中,在增量函数中,条件变量在实际增加计数(从零开始)之前发出信号。增加计数后是否不应该调用信号?还是在 increment_function 中释放 mutex 之前,decrement_count 函数中的等待调用不会返回?
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
decrement_count()
pthread_mutex_lock(&count_lock);
while (count == 0)
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
pthread_mutex_unlock(&count_lock);
increment_count()
pthread_mutex_lock(&count_lock);
if (count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
【问题讨论】:
【参考方案1】:因为互斥锁,不管是在信号之前还是之后做都没有关系,因为在互斥锁解锁之前无法读取变量。
【讨论】:
所以在递减函数中的等待调用不会返回,直到条件变量发出信号并且互斥锁在递增函数中解锁? 对了,当进入cond wait时,它解锁了mutex,当它重新唤醒时,它再次锁定了mutex,所以因为在增量函数中锁住了mutex,所以cond不会醒来直到解锁。【参考方案2】:作为Troy says,在递增counter
之前向条件变量发出信号是可以的,因为这些操作都是在持有互斥体的情况下完成的。
但是,如果多个线程可以在decrement_count()
中等待,则此代码确实存在一个细微的错误。考虑两个线程在pthread_cond_wait()
中挂起的情况,count == 0
。现在,increment_count()
被连续调用两次(可能由同一个线程调用)——count
应该是递增到2
,但条件变量只发出一次信号。这意味着只有 一个 等待线程被唤醒,而另一个将无限期等待,即使 counter
不为零。
可以通过多种方式修复此错误:
在increment_count()
中将pthread_cond_signal()
替换为pthread_cond_broadcast()
;或
在increment_count()
中无条件调用pthread_cond_signal()
;或
如果count
在decrement_count()
中递减后非零,则调用pthread_cond_signal()
。
一般情况下,请记住使用pthread_cond_signal()
而不是pthread_cond_broadcast()
是一种优化,使用时应仔细分析算法是否仍然正确。
【讨论】:
以上是关于条件变量信号的主要内容,如果未能解决你的问题,请参考以下文章
[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)
[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)
[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)