簡單介紹一下使用條件變量時镰吵,增加互斥鎖的必要性专肪。pthread_cond_wait的API如下
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
條件變量的用法就不具體介紹了适袜,此處我們考慮的問題是增加mutex參數(shù)的必要性哲泊,先看看課本中的使用方法(只貼了主要的部分剩蟀,包含生產(chǎn)者和消費者線程):
#include <stdio.h>
#include <pthread.h>
#define MAX 1000000000
pthread_mutex_t the_mutex;/*互斥鎖*/
pthread_cond_t condc, condp;/*消費者和生產(chǎn)者條件變量*/
int buffer = 0;
void *producer(void *ptr)
{
int i;
for(i = 1; i <= MAX; i++)
{
pthread_mutex_lock(&the_mutex);
while(buffer != 0)/*1*/
{
pthread_cond_wait(&condp, &the_mutex);/*2*/
}
buffer = i;
pthread_cond_signal(&condc);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
void *consumer(void *ptr)
{
int i;
for(i = 1; i <= MAX; i++)
{
pthread_mutex_lock(&the_mutex);
while(buffer == 0)/*3*/
{
pthread_cond_wait(&condc, &the_mutex);/*4*/
}
buffer = 0;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
線程在調(diào)用pthread_cond_wait并導致阻塞時會解鎖互斥鎖,解除阻塞并離開pthread_cond_wait時會加鎖互斥鎖切威。從代碼中可以看到育特,該特性可以保證語句<1>和語句<3>中對buffer的訪問和之后調(diào)用pthread_cond_wait導致的阻塞操作的原子性。
上面的解釋可能不夠直觀先朦,我們考慮一種錯誤的用法(去掉互斥鎖)缰冤,代碼如下:
void *producer(void *ptr)
{
int i;
for(i = 1; i <= MAX; i++)
{
while(buffer != 0)/*1*/
{
pthread_cond_wait(&condp, NULL);/*2*/
}
buffer = i;
pthread_cond_signal(&condc);
}
pthread_exit(0);
}
void *consumer(void *ptr)
{
int i;
for(i = 1; i <= MAX; i++)
{
while(buffer == 0)/*3*/
{
pthread_cond_wait(&condc, NULL);/*4*/
}
buffer = 0;
pthread_cond_signal(&condp);
}
pthread_exit(0);
}
我們考慮一種可能的線程運行時序,如下所示(buffer初始值為0):
從圖中可以看到在consumer線程對buffer進行訪問并準備阻塞的時候喳魏,切換至producer線程運行棉浸,該線程更改了buffer的值,最終導致兩個線程均被阻塞刺彩,發(fā)生死鎖迷郑。
由此可以看出,在使用條件變量時创倔,對需要判斷的條件添加互斥鎖的必要性嗡害。