使用流程
等待線程:
pthread_mutex_lock(&mutex);
if(條件不滿足)
pthread_cond_wait(&cond, &mutex);
//處理共享資源
pthread_mutex_unlock(&mutex);
激活線程:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
下面寫了一個例子
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <iostream>
using namespace std;
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//該函數增加count數值
void * creator(void * arg)
{
cout << "creator add lock" << endl;
pthread_mutex_lock(&mutex);
count ++;
cout << "in creator count is : " << count << endl;
//條件滿足時發送信號
if(count > 0)
{
pthread_cond_signal(&cond);
}
cout << "creator release lock" << endl;
pthread_mutex_unlock(&mutex);
return NULL;
}
//該函數減少count數值
void * consumer(void * arg)
{
cout << "consumer add lock" << endl;
pthread_mutex_lock(&mutex);
//當條件不滿足時等待
if(count <= 0)
{
cout << "begin wait" << endl;
pthread_cond_wait(&cond,&mutex);
cout << "end wait" << endl;
}
count --;
cout << "in consumer count is " << count << endl;
pthread_mutex_unlock(&mutex);
cout << "consumer release lock" << endl;
return NULL;
}
int main()
{
//兩個線程,一個生產者線程一個消費者線程
pthread_t createthread,consumethread;
pthread_create(&consumethread, NULL, consumer, NULL);
sleep(2);
pthread_create(&createthread, NULL, creator, NULL);
//主進程等待兩個線程結束
pthread_join(createthread, NULL);
pthread_join(consumethread, NULL);
return 0;
}
因爲消費者線程先跑起來,會等待生產者增加count數量,所以打印輸出結果如下
下面將消費者和生產者線程增加幾個,creater和consumer內部用循環處理,
這樣就能看出效果了。
void * creator(void * arg)
{
int i = 0;
while(i<300)
{
i++;
cout << "creator add lock" << endl;
pthread_mutex_lock(&mutex);
count ++;
cout << "in creator count is : " << count << endl;
if(count > 0)
{
pthread_cond_signal(&cond);
}
cout << "creator release lock" << endl;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
void * consumer(void * arg)
{
int i = 0;
while(i < 100)
{
i++;
cout << "consumer add lock" << endl;
pthread_mutex_lock(&mutex);
if(count <= 0)
{
cout << "begin wait" << endl;
pthread_cond_wait(&cond,&mutex);
cout << "end wait" << endl;
}
count --;
cout << "in consumer count is " << count << endl;
pthread_mutex_unlock(&mutex);
cout << "consumer release lock" << endl;
}
return NULL;
}
int main()
{
pthread_t createthread[2],consumethread[3];
for(int i = 0; i < 3; i++)
{
pthread_create(&consumethread[i], NULL, consumer, NULL);
}
for(int i = 0; i < 2; i++)
{
pthread_create(&createthread[i], NULL, creator, NULL);
}
for(int i = 0; i < 2; i++)
{
pthread_join(createthread[i], NULL);
}
for(int i = 0; i < 3; i++)
{
pthread_join(consumethread[i], NULL);
}
return 0;
}
==============================================================================================================
接下來講解使用while和if判斷線程執行條件是否成立的區別。一般來說,在多線程資源競爭的時候,在一個使用資源的線程裏面(消費者)判斷資源是否可用,不可用便調用pthread_cond_wait,在另一個線程裏面(生產者)如果判斷資源可用的話,則調用pthread_cond_signal發送一個資源可用信號。但是在wait成功之後,資源就一定可以被使用麼,答案是否定的,如果同時有兩個或者兩個以上的線程正在等待此資源,wait返回後,資源可能已經被使用了,在這種情況下,應該使用:
while(resource == FALSE)
pthread_cond_wait(&cond, &mutex);
如果之後一個消費者,那麼使用if就可以了。解釋一下原因,分解pthread_cond_wait的動作爲以下幾步:
1,線程放在等待隊列上,解鎖
2,等待 pthread_cond_signal或者pthread_cond_broadcast信號之後去競爭鎖
3,若競爭到互斥索則加鎖。
上面講到,有可能多個線程在等待這個資源可用的信號,信號發出後只有一個資源可用,但是有A,B兩個線程都在等待,B比較速度快,獲得互斥鎖,然後加鎖,消耗資源,然後解鎖,之後A獲得互斥鎖,但他回去發現資源已經被使用了,它便有兩個選擇,一個是去訪問不存在的資源,另一個就是繼續等待,那麼繼續等待下去的條件就是使用while,要不然使用if的話pthread_cond_wait返回後,就會順序執行下去。
下面來講一下:pthread_cond_wait和pthread_cond_singal是怎樣配對使用的:
等待線程:
pthread_cond_wait前要先加鎖
pthread_cond_wait內部會解鎖,然後等待條件變量被其它線程激活
pthread_cond_wait被激活後會再自動加鎖
激活線程:
加鎖(和等待線程用同一個鎖)
pthread_cond_signal發送信號(階躍信號前最好判斷有無等待線程)
解鎖
激活線程的上面三個操作在運行時間上都在等待線程的pthread_cond_wait函數內部。