在不locking互斥锁的情况下调用pthread_cond_signal

我读了一个地方,我们应该在调用pthread_cond_signal之前locking互斥锁 ,并在调用它之后解锁互斥锁

pthread_cond_signal()例程用于发送(或唤醒)等待条件variables的另一个线程。 它应该在locking互斥锁之后调用,并且必须解锁互斥锁才能完成pthread_cond_wait()例程。

我的问题是:是不是可以调用pthread_cond_signalpthread_cond_broadcast方法而不locking互斥锁?

如果您不locking代码path中的互斥锁,这会改变条件和信号,则可能会失去唤醒。 考虑这一对过程:

过程A:

pthread_mutex_lock(&mutex); while (condition == FALSE) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); 

过程B(不正确):

 condition = TRUE; pthread_cond_signal(&cond); 

然后考虑这种可能的交叉指令,其中condition开始为FALSE

 Process A Process B pthread_mutex_lock(&mutex); while (condition == FALSE) condition = TRUE; pthread_cond_signal(&cond); pthread_cond_wait(&cond, &mutex); 

condition现在为TRUE ,但进程A停留在等待条件variables – 它错过了唤醒信号。 如果我们改变进程B来locking互斥锁:

过程B(正确):

 pthread_mutex_lock(&mutex); condition = TRUE; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); 

…那么上面不会发生; 唤醒将永远不会被错过。

(请注意,实际上可以pthread_cond_signal()之后移动pthread_cond_signal()本身,但是这可能导致线程的优化调度较less,并且由于更改了条件本身,您必须locking此代码path中已有的互斥锁)。

根据这本手册:

线程可以调用 pthread_cond_broadcast()pthread_cond_signal()函数,不pipe它是否当前拥有调用pthread_cond_wait()pthread_cond_timedwait()线程在等待期间与条件variables相关联的互斥锁 ; 然而,如果需要可预测的调度行为,则该线程将被调用pthread_cond_broadcast()pthread_cond_signal()的线程locking。

可预测的调度行为语句的含义由comp.programming.threads上的Dave Butenhof( 编程使用POSIX线程的作者)解释,可在此处find 。

caf,在您的示例代码中,进程B修改condition而不先locking互斥锁。 如果进程B在修改过程中简单地locking了互斥锁,然后在调用pthread_cond_signal之前仍然解锁了互斥锁,那么就没有问题了 – 我是对的吗?

我直觉地认为,咖啡的位置是正确的:调用pthread_cond_signal而不拥有互斥锁是一个坏主意。 但是caf的例子实际上并不支持这一立场。 它只是支持更弱(实际上不言而喻)的立场的证据,除非您先locking了互斥体,否则修改由互斥体保护的共享状态是一个不好的想法。

任何人都可以提供一些示例代码,其中调用pthread_cond_signal紧接着pthread_mutex_unlock产生正确的行为,但调用pthread_mutex_unlock紧接着pthread_cond_signal产生不正确的行为?