【Linux】Linux 条件变量 为什么要配合互斥锁
官方:
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的。