条件变量信号

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();或 如果countdecrement_count() 中递减后非零,则调用pthread_cond_signal()

一般情况下,请记住使用pthread_cond_signal()而不是pthread_cond_broadcast()是一种优化,使用时应仔细分析算法是否仍然正确。

【讨论】:

以上是关于条件变量信号的主要内容,如果未能解决你的问题,请参考以下文章

[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)

[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)

[C++11 多线程同步] --- 条件变量的那些坑条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)

条件变量信号

条件变量与信号量

信号量与条件变量的区别