pthread_cond_signal 来自多个线程
pthread_cond_signal from multiple threads
让我们假设有一个线程调用 pthread_cond_wait
并等待信号:
pthread_mutex_lock(&m);
.....
while(run)
{
do {
pthread_cond_wait(&cond,&m);
} while(!got_signal);
got_signal = false;
do_something();
}
并且有多个线程应该传递信号:
pthread_mutex_lock(&m);
got_signal = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
这个解决方案足够安全吗?如果多个线程发送信号会发生什么? m
mutex 是否足以保证所有信号都被序列化并且不会丢失?
在您发布的代码中,唯一允许线程调用 pthread_cond_signal()
的地方是它们可以获取 m
,并且只有当您的等待线程在 [= 上被阻塞时才会发生这种情况14=].
但是,在等待线程被唤醒并可以获取互斥锁之前,两个发信号线程可能会先获取互斥锁。在这种情况下,您将丢失第二个信号(以及此后可能到达的任何其他信号,在等待线程 运行s 之前),因为您的等待线程只能 "see" 它已收到信号,但不知道发生了多少次。
为确保您不会丢失任何信号,您可以使用计数器代替 got_signal
标志:
等待线程:
pthread_mutex_lock(&m);
.....
while(run)
{
while(signal_count == 0) {
pthread_cond_wait(&cond,&m);
}
--signal_count;
do_something();
}
信号线程:
pthread_mutex_lock(&m);
++signal_count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
(另请注意,我已将 do...while
循环替换为 while
循环,以确保在仍有未处理的信号时不会调用 pthread_cond_wait()
。 )
现在,如果多个线程最终直接发出信号,signal_count
将变得不止一个,这将导致等待线程 运行 其 do_something()
多次只有一次。
让我们假设有一个线程调用 pthread_cond_wait
并等待信号:
pthread_mutex_lock(&m);
.....
while(run)
{
do {
pthread_cond_wait(&cond,&m);
} while(!got_signal);
got_signal = false;
do_something();
}
并且有多个线程应该传递信号:
pthread_mutex_lock(&m);
got_signal = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
这个解决方案足够安全吗?如果多个线程发送信号会发生什么? m
mutex 是否足以保证所有信号都被序列化并且不会丢失?
在您发布的代码中,唯一允许线程调用 pthread_cond_signal()
的地方是它们可以获取 m
,并且只有当您的等待线程在 [= 上被阻塞时才会发生这种情况14=].
但是,在等待线程被唤醒并可以获取互斥锁之前,两个发信号线程可能会先获取互斥锁。在这种情况下,您将丢失第二个信号(以及此后可能到达的任何其他信号,在等待线程 运行s 之前),因为您的等待线程只能 "see" 它已收到信号,但不知道发生了多少次。
为确保您不会丢失任何信号,您可以使用计数器代替 got_signal
标志:
等待线程:
pthread_mutex_lock(&m);
.....
while(run)
{
while(signal_count == 0) {
pthread_cond_wait(&cond,&m);
}
--signal_count;
do_something();
}
信号线程:
pthread_mutex_lock(&m);
++signal_count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
(另请注意,我已将 do...while
循环替换为 while
循环,以确保在仍有未处理的信号时不会调用 pthread_cond_wait()
。 )
现在,如果多个线程最终直接发出信号,signal_count
将变得不止一个,这将导致等待线程 运行 其 do_something()
多次只有一次。