假设我有4个线程,一个生产者和三个消费者,一个互斥锁和一个条件变量,每个消费者都运行与下面相同的功能:
mutexlock(mutex)
signal[i] = 1;
while(signal[i] == 1) {
condwait(cond, mutex)
}
mutexunlock(mutex)
制作人做了以下
if(signal == 1)
{
set 0 - atomically using CAS
mutexlock(mutex)
condbroadcast(cond)
mutexunlock(mutex)
}
让我们说如果不止一个消费者在那个锁中,他们不会争夺cond变量吗?我应该为每个线程创建一个,还是可以在没有任何竞争条件的情况下在多个线程中共享p_thread条件变量?
答案 0 :(得分:0)
当你创建一个多线程程序时,它们共享资源信号[i]并且所有三个线程都将竞争资源。当signal [i] == 0时,没有得到的线程资源将被放入条件变量的队列中。当你发送一个广播时,条件变量中的所有等待线程都会弱化并竞争资源。这里是多线程初学者的tourial下进行。
答案 1 :(得分:0)
pthread_cond_wait
的语义是释放获取的互斥锁并阻塞条件变量。当信号到达时,块被释放,然后pthread_cond_wait
获取互斥锁上的锁。
因此,在您的情况下,当您使用pthread_cond_broadcast
时,在条件上阻止的所有线程都将超过此点,但在此之后,其中一个将被授予对互斥锁的锁定。哪一个?它取决于调度程序在解除阻塞后唤醒它们的顺序,以及在两个或多个线程尝试在某个时刻获取锁定的情况下的pthread实现。可以认为它是随机的。
如果用pthread_cond_broadcast
替换pthread_cond_signal
,信号将被传递到某些线程。是的,它应该是一个,但有时可以从条件变量中释放多个。仍然,调度程序将选择传递信号的线程(或多个线程)。如果不止一个人从cond等待中醒来,他们就会为互斥锁而战。如前所述 - 您可以将结果视为随机。
让我们看看documentation:
顺便说一句,我很好奇。最近有几个关于条件变量的问题(你们都为你的大学做什么项目或者什么?)在过去24小时里我看到的每一个问题中我都看到了以下信号模式:如果在条件变量上阻塞了多个线程,则调度策略应确定线程被解除阻塞的顺序。
在多处理器上,pthread_cond_signal()的实现可能无法避免在条件变量上阻塞多个线程的阻塞。
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond); /* or signal */
pthread_mutex_unlock(&mutex);
等待线程时:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
/* do something */
pthread_mutex_unlock(&mutex);
背后的原因是什么?
等待线程等待cond
,mutex
被释放。因此,信令线程获取mutex
上的锁定,发出其他线程的信号。在这个时刻,他们仍然在pthread_cond_wait
封锁之后的cond
进度内,然后他们试图获得mutex
上的锁定。而且,当然,他们不能,因为锁是由信令线程保持的。然后,信令线程释放mutex
和等待线程最终可以通过逐个获取mutex
来处理。
对于信号编写者和等待消费者,这种模式应如下所示。
对于作家:
while(loop_condition) {
prepare_data() /* it could be a long process */
lock(&mutex);
add_data_to_queue(); /* fast, inside critical section */
unlock(&mutex);
signal(&cond); /* or broadcast */
}
对于消费者:
while(consumer_loop_condition) {
lock(&mutex);
while(!data_ready_to_process()) {
wait(&cond,&mutex);
}
fetch_data(); /* fast, still inside critical section */
unlock(&mutex);
if(got_data) {
process_data(); /* could be a long process */
}
}
另请参阅this answer以获取有关cond /互斥锁和一些示例代码的更多说明。