LinuxLinux 条件变量 为什么要配合互斥锁

Posted liangchaoxi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LinuxLinux 条件变量 为什么要配合互斥锁相关的知识,希望对你有一定的参考价值。

官方:

A condition variable must always be associated with a mutex,  to  avoid
       the race condition where a thread prepares to wait on a condition vari‐
       able and another thread signals the condition  just  before  the  first
       thread actually waits on it.

条件变量必须始终与互斥锁配合,以避免竞争状态:其中线程准备等待一个条件,另一个线程刚好在第一个线程 真正等待 之前发出条件信号。

网友:

pthread_cond_wait总和一个互斥锁结合使用。在调用pthread_cond_wait前要先获取锁。pthread_cond_wait函数执行时先自动释放指定的锁,然后等待条件变量的变化。

 来看一个例子(你是否能理解呢?):

In Thread1:

pthread_mutex_lock(&m_mutex);
pthread_cond_wait(&m_cond,&m_mutex);
pthread_mutex_unlock(&m_mutex);



In Thread2:

pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);

为什么要与pthread_mutex 一起使用呢? 这是为了应对 线程1在调用pthread_cond_wait()但线程1还没有进入wait cond的状态的时候,此时线程2调用了 cond_singal 的情况。 如果不用mutex锁的话,这个cond_singal就丢失了。

加了锁的情况是,线程2必须等到 mutex 被释放(也就是 pthread_cod_wait() 释放锁并进入wait_cond状态 ,此时线程2上锁) 的时候才能调用cond_singal.

​http://blog.chinaunix.net/uid-27164517-id-3282242.html​

我的理解:

为了将条件判断和wait变成一个原子操作。

void function_2() {
int data = 0;
while ( data != 1) {
std::unique_lock<std::mutex> locker(mu);
while(q.empty())
cond.wait(locker); // Unlock mu and wait to be notified
data = q.back();
q.pop_back();
locker.unlock();
std::cout << "t2 got a value from t1: " << data << std::endl;
}
}

 while(q.empty())
cond.wait(locker); // Unlock mu and wait to be notified

如果不加锁,在线程2判断q.empty()后(如果为true),然后跳过这一步准备下一步cond.wait, 如果此时线程1修改q,然后发出notify,结果因为线程2还没进入cond.wait,这个notify就被线程2给错过了,然后线程2完成进入cond.wait,只能等下一个notify了,如果没有下一个notify或者下一个notify依赖于线程2,那就一直卡在那里。

而如果加了锁,那判断q.empty()和cond.wait就变成一个原子操作,线程2在完成cond.wait之前,线程1是改不了q的。

 

以上是关于LinuxLinux 条件变量 为什么要配合互斥锁的主要内容,如果未能解决你的问题,请参考以下文章

为啥 pthread 的条件变量函数需要互斥锁?

Linux下的互斥锁和条件变量

信号量,互斥锁,读写锁和条件变量的区别

使用条件变量优于互斥锁的优点

使用条件变量进行线程间的同步

条件变量和互斥锁的使用