在下面的(伪)代码中,cond
可能会因为任何原因而无法唤醒。所以我在那里放了一个while循环。当它确实唤醒时,它仍将消耗锁,因此可以保证在out()
中只有一个线程正在执行其工作。
但是,如果out()
中有一个虚假的唤醒,同时in()
向out()
发出信号,会发生什么情况,但是在那个时刻out()
已被锁定,因为虚假的唤醒。那么如果cond
向锁定线程发出信号会发生什么呢?
in()
inLock.lock()
isEmpty = false
cond.signal()
inLock.unlock()
out()
outLock.lock()
while isEmpty
cond.wait(outLock)
isEmpty = true
outLock.unlock()
注
嗯,为了100%安全,我知道我可以为in()
和out()
使用一个互斥锁,但我使用的数据结构在输入和输入时是100%安全的输出同时发生;它是一种队列。而且我认为在填充一些新数据时阻止从队列中读出的任何内容都会影响性能,反之亦然。
我确实考虑过使用信号量,但问题是许多C和C ++库无论出于何种原因都不能实现信号量。
答案 0 :(得分:5)
当in()
线程集isEmpty = false
和out()
线程测试while (isEmpty)
时,您必须使用相同的互斥锁。否则,可能会发生这种情况:
out()
线程测试isEmpty
,发现它是真的; in()
线程将isEmpty
设置为false并发出条件变量信号(但没有人醒来,因为没有人等待); out()
线程调用cond.wait()
并永远阻止,尽管队列不再是空的。请注意,在这个序列中,没有一个虚假的唤醒 - 它只是一个普通的老竞争条件。
只要您使用与测试isEmpty
时相同的互斥锁更新isEmpty
,就无法进行此交错。
答案 1 :(得分:2)
那么如果cond向锁定的线程发出信号会发生什么?
信号永远消失。如果在调用pthread_cond_signal
时没有线程正在等待信号,那么pthread_cond_signal
什么都不做。
答案 2 :(得分:2)
由于isEmpty
正由两个不同的线程读取和修改,因此在不受保护的情况下访问它是错误的。当您允许in
和out
使用不同的锁实例时,这基本上就是您正在做的事情。
在同一条件变量上使用不同的锁实例违反了POSIX API for pthread_cond_wait()
(强调我的)。
在同一条件变量上使用多个互斥锁对并发
pthread_cond_wait()
或pthread_cond_timedwait()
操作的影响未定义;也就是说,当一个线程等待条件变量时,一个条件变量就会绑定到一个唯一的互斥锁,并且当等待返回时,这个(动态)绑定就会结束。