Mey*_*sam 78 c++ mutex signals pthreads condition-variable
我在某处读到我们应该在调用pthread_cond_signal之前锁定互斥锁并在调用它后解锁互斥锁:
pthread_cond_signal()例程用于发信号(或唤醒)正在等待条件变量的另一个线程.它应该在锁定互斥锁后调用,并且必须解锁互斥锁才能完成pthread_cond_wait()例程.
我的问题是:在不锁定互斥锁的情况下调用pthread_cond_signal或pthread_cond_broadcast方法是不是可以?
caf*_*caf 136
如果未在代码路径中锁定互斥锁以更改条件和信号,则可能会丢失唤醒.考虑这对过程:
流程A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Run Code Online (Sandbox Code Playgroud)
流程B(不正确):
condition = TRUE;
pthread_cond_signal(&cond);
Run Code Online (Sandbox Code Playgroud)
然后考虑这种可能的指令交错,其condition开头为FALSE:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
Run Code Online (Sandbox Code Playgroud)
现在condition是TRUE,但是进程A等待条件变量 - 它错过了唤醒信号.如果我们改变进程B来锁定互斥锁:
流程B(正确):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
Run Code Online (Sandbox Code Playgroud)
......那么上面就不会发生; 唤醒永远不会错过.
(请注意,您实际上可以在pthread_cond_signal()自身之后移动自身pthread_mutex_unlock(),但这可能会导致线程的优化调度不佳,并且由于更改条件本身,您必须已锁定此代码路径中的互斥锁).
ice*_*ime 47
根据本手册:
该
pthread_cond_broadcast()或pthread_cond_signal()功能 可以由一个线程是当前是否拥有互斥体被称为该线程调用pthread_cond_wait()或pthread_cond_timedwait()已与在他们等待的条件变量相关联; 但是,如果需要可预测的调度行为,那么该互斥锁应由线程调用pthread_cond_broadcast()或 锁定pthread_cond_signal().
Dave Butenhof(编程与POSIX线程的作者)在comp.programming.threads上解释了可预测调度行为语句的含义,可在此处获得.
caf,在示例代码中,流程B进行了修改,condition而没有先锁定互斥锁。如果进程B在修改过程中只是简单地锁定了互斥锁,然后在调用之前仍然解锁了互斥锁pthread_cond_signal,那将没有问题---我是否正确?
我直觉上相信caf的位置是正确的:pthread_cond_signal不拥有互斥锁就打电话是个坏主意。但是,caf的榜样实际上并不是支持这一立场的证据。仅是证明弱点(实际上是不言而喻)的证据,除非您先锁定了该互斥锁,否则修改由互斥锁保护的共享状态是一个坏主意。
谁能提供一些示例代码,其中调用pthread_cond_signal后pthread_mutex_unlock产生正确的行为,但调用pthread_mutex_unlock后pthread_cond_signal产生错误的行为?