與條件變量相關API
? ??????條件變量是線程另一可用的同步機制。條件變量給多個線程提供了一個會合的場所。條件變量與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發生。
? ??????條件本身是由互斥量保護的。線程在改變條件狀態前必須首先鎖住互斥量,其他線程在獲得互斥量之前不會察覺到這種改變,因為必須鎖定互斥量以后才能計算條件。
? ??????條件變量使用之前必須首先初始化,pthread_cond_t數據類型代表的條件變量可以用兩種方式進行初始化,可以把常量? ??????PTHREAD_COND_INITIALIZER賦給靜態分配的條件變量,但是如果條件變量是動態分配的,可以使用pthread_cond_destroy函數對條件變量進行去除初始化(deinitialize)。
1. 創建及銷毀條件變量
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t*restrict cond);
// 返回:若成功返回0,否則返回錯誤編號
除非需要創建一個非默認屬性的條件變量,否則pthread_cont_init函數的attr參數可以設置為NULL。cond參數是條件也要進行定義和初始化
2. 等待
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);//這個是立即返回
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);//這個是等待一段時間后返回
// 返回:若成功返回0,否則返回錯誤編號
? ??????pthread_cond_wait等待條件變為真。如果在給定的時間內條件不能滿足,那么會生成一個代表一個出錯碼的返回變量。傳遞給pthread_cond_wait的互斥量對條件進行保護,調用者把鎖住的互斥量傳給函數。函數把調用線程放到等待條件的線程列表上,然后對互斥量解鎖,這兩個操作都是原子操作。這樣就關閉了條件檢查和線程進入休眠狀態等待條件改變這兩個操作之間的時間通道,這樣線程就不會錯過條件的任何變化。pthread_cond_wait返回時,互斥量再次被鎖住。
? ??????pthread_cond_timedwait函數的工作方式與pthread_cond_wait函數類似,只是多了一個timeout。timeout指定了等待的時間,它是通過timespec結構指定。
3. 觸發
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t*restrict cond);
int pthread_cond_broadcast(pthread_cond_t *restrict cond);
// 返回:若成功返回0,否則返回錯誤編號
這兩個函數可以用于通知線程條件已經滿足。pthread_cond_signal函數將喚醒等待該條件的某個線程,而pthread_cond_broadcast函數將喚醒等待該條件的所有進程。
注意一定要在改變條件狀態以后再給線程發信號。
代碼示例
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);int g_data=0;//pthread_mutex_t mutex;
pthread_cond_t cond;void*func1(void *arg)
{static cnt=0;printf("t1 :%ld thread is created\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int*)arg));while(1){pthread_cond_wait(&cond,&mutex);printf("t1 over==============================\n");printf("t1 :%d\n",g_data);g_data=0;sleep(1);if(cnt++==10){exit(1);}}}void*func2(void *arg)
{printf("t2 :%ld thread is created\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int*)arg));while(1){printf("t2 printf is %d\n",g_data);pthread_mutex_lock(&mutex);g_data++;if(g_data==3){pthread_cond_signal(&cond);}pthread_mutex_unlock(&mutex);sleep(1);}pthread_mutex_unlock(&mutex);
}int main()
{int ret;int param=100;pthread_t t1;pthread_t t2;pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);ret=pthread_create(&t1,NULL,func1,(void*)¶m);if(ret==0){// printf("main:create t1 success\n");}ret=pthread_create(&t2,NULL,func2,(void*)¶m);if(ret==0){
// printf("main:create t2 success\n");}
// printf("main : %ld \n",(unsigned long)pthread_self());pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}
//其中func1中的cnt是測試用的
以下代碼可以用試:
CLC@Embed_Learn:~/xiancheng$ gcc demo8.c -lpthread -odemo8
CLC@Embed_Learn:~/xiancheng$ vi text1.c
CLC@Embed_Learn:~/xiancheng$ ./a.out 10 >>test.ret.txt &(其中>>表示將運行的結果追加到test.ret.txt中 &表示在后臺運行)
[1] 21313(這是進程的ID號)
初始化
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
//靜態初始化
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
//動態初始化
參考博文:https://www.cnblogs.com/xiehongfeng100/p/4620852.html