C++ 在不锁定互斥锁的情况下调用 pthread_cond_signal

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4544234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:41:44  来源:igfitidea点击:

Calling pthread_cond_signal without locking mutex

c++pthreadsmutexsignalscondition-variable

提问by Meysam

I read somewhere that we should lock the mutexbefore calling pthread_cond_signaland unlock the mutext after calling it:

我在某处读到我们应该在调用pthread_cond_signal之前锁定互斥锁并在调用它之后解锁互斥锁

The pthread_cond_signal() routine is used to signal (or wake up) another thread which is waiting on the condition variable. It should be called after mutex is locked, and must unlock mutex in order for pthread_cond_wait() routine to complete.

pthread_cond_signal() 例程用于通知(或唤醒)另一个正在等待条件变量的线程。它应该在互斥锁被锁定后调用,并且必须解锁互斥锁才能完成 pthread_cond_wait() 例程。

My question is: isn't it OK to call pthread_cond_signalor pthread_cond_broadcastmethods without locking the mutex?

我的问题是:在不锁定互斥锁的情况下调用pthread_cond_signalpthread_cond_broadcast方法不是可以吗?

回答by caf

If you do not lock the mutex in the codepath that changes the condition and signals, you can lose wakeups. Consider this pair of processes:

如果不锁定更改条件和信号的代码路径中的互斥锁,则可能会丢失唤醒。考虑这对进程:

Process A:

流程一:

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

Process B (incorrect):

流程B(错误):

condition = TRUE;
pthread_cond_signal(&cond);

Then consider this possible interleaving of instructions, where conditionstarts out as FALSE:

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

Process A                             Process B

pthread_mutex_lock(&mutex);
while (condition == FALSE)

                                      condition = TRUE;
                                      pthread_cond_signal(&cond);

pthread_cond_wait(&cond, &mutex);

The conditionis now TRUE, but Process A is stuck waiting on the condition variable - it missed the wakeup signal. If we alter Process B to lock the mutex:

现在conditionTRUE,但进程 A 卡在等待条件变量 - 它错过了唤醒信号。如果我们改变进程 B 来锁定互斥锁:

Process B (correct):

流程B(正确):

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

...then the above cannot occur; the wakeup will never be missed.

...则上述情况不会发生;永远不会错过唤醒。

(Note that you canactually move the pthread_cond_signal()itself after the pthread_mutex_unlock(), but this can result in less optimal scheduling of threads, and you've necessarily locked the mutex already in this code path due to changing the condition itself).

(请注意,您实际上可以pthread_cond_signal()之后移动本身pthread_mutex_unlock(),但这可能会导致线程的最佳调度降低,并且由于更改条件本身,您必须锁定此代码路径中已经存在的互斥锁)。

回答by icecrime

According to this manual :

根据本手册:

The pthread_cond_broadcast()or pthread_cond_signal()functions may be called by a thread whether or not it currently owns the mutexthat threads calling pthread_cond_wait()or pthread_cond_timedwait()have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast()or pthread_cond_signal().

pthread_cond_broadcast()pthread_cond_signal()功能 可以通过它是否当前拥有互斥线程调用的线程调用pthread_cond_wait()pthread_cond_timedwait()已与在他们等待的条件变量相关联; 但是,如果需要可预测的调度行为,则该互斥锁应由线程调用pthread_cond_broadcast()或 锁定 pthread_cond_signal()

The meaning of the predictable scheduling behaviorstatement was explained by Dave Butenhof (author of Programming with POSIX Threads) on comp.programming.threads and is available here.

Dave Butenhof(Programming with POSIX Threads 的作者)在 comp.programming.threads 上解释了可预测调度行为语句的含义,可在此处获取

回答by Quuxplusone

caf, in your sample code, Process B modifies conditionwithout locking the mutex first. If Process B simply locked the mutex during that modification, and then still unlocked the mutex before calling pthread_cond_signal, there would be no problem --- am I right about that?

caf,在您的示例代码中,进程 B 修改时condition没有先锁定互斥锁。如果进程 B 只是在修改过程中锁定了互斥锁,然后在调用 之前仍然解锁了互斥锁pthread_cond_signal,那就没有问题了——我是对的吗?

I believe intuitively that caf's positionis correct: calling pthread_cond_signalwithout owning the mutex lock is a Bad Idea. But caf's exampleis not actually evidence in support of this position; it's simply evidence in support of the much weaker (practically self-evident) position that it is a Bad Idea to modify shared state protected by a mutex unless you have locked that mutex first.

我直觉地相信 caf 的立场是正确的:在pthread_cond_signal不拥有互斥锁的情况下调用是一个坏主意。但 caf 的例子实际上并不是支持这一立场的证据;这只是支持更弱(实际上不言而喻)立场的证据,即修改受互斥锁保护的共享状态是一个坏主意,除非您先锁定了该互斥锁。

Can anyone provide some sample code in which calling pthread_cond_signalfollowed by pthread_mutex_unlockyields correct behavior, but calling pthread_mutex_unlockfollowed by pthread_cond_signalyields incorrect behavior?

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