p_threads:条件变量锁定

时间:2017-06-06 03:40:03

标签: c multithreading pthreads mutex condition-variable

假设我有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条件变量?

2 个答案:

答案 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

  

如果在条件变量上阻塞了多个线程,则调度策略应确定线程被解除阻塞的顺序。

     

在多处理器上,pthread_cond_signal()的实现可能无法避免在条件变量上阻塞多个线程的阻塞。

顺便说一句,我很好奇。最近有几个关于条件变量的问题(你们都为你的大学做什么项目或者什么?)在过去24小时里我看到的每一个问题中我都看到了以下信号模式:

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);

背后的原因是什么?

等待线程等待condmutex被释放。因此,信令线程获取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 /互斥锁和一些示例代码的更多说明。