线程控制(一)
1. 線程執行順序問題
#include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h>void *thread1(void *); void *thread2(void *);pthread_key_t key;void *thread1(void *arg){int a = 1, *tsd = &a;pthread_t thid2;printf("thread1 %lu is running\n", pthread_self());pthread_setspecific(key, tsd);pthread_create(&thid2, NULL, thread2, NULL);sleep(3); //---2tsd = (int *)pthread_getspecific(key);printf("thread1 %lu returns %d\n", pthread_self(), *tsd);return (void *)0; }void *thread2(void *arg){int a = 5, *tsd = &a;printf("thread2 %lu is running\n", pthread_self());pthread_setspecific(key, (int *)tsd);tsd = (int *)pthread_getspecific(key);printf("thread2 %lu returns %d\n", pthread_self(), *tsd);//tsd is a pointerreturn (void *)0; }int main(int argc, char const *argv[]) {pthread_t thid1;printf("main thread is running\n");pthread_key_create(&key, NULL);pthread_create(&thid1, NULL, thread1, NULL);sleep(5); //---1pthread_key_delete(key);printf("main thread exit\n");return 0; }1)代碼1、2處都不注釋,運行結果:
2)代碼中2處注釋掉,1保留,運行結果:
3)代碼中1處注釋掉,2保留,運行結果:
奇怪的現象發生了!!
我們會發現,在第3種情況中,竟然只有main函數中的內容輸出了,而子線程好像沒有運行。為什么呢?原來,在用戶沒有設定線程間的調度策略時,系統默認采取基于時間片輪轉的調度策略。此時,子線程要在主線程空閑的條件下才會執行,假設主線程一直在工作,那么子線程沒有機會運行,直到主線程退出。
然而,由于線程間共享資源,主線程的退出會影響到該進程下的所有線程,所以子線程就永遠沒有機會執行,也就造成了第3種只有main函數中的內容輸出了。
而使用sleep函數會讓程序掛起一段時間,讓子進程得到運行的機會,所以前兩種情況所有函數中內容都有輸出,只是順序不同而已。當然,子線程的執行順序也是不確定的,這就要看操作系統的具體分配了。
2. 條件變量的使用
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); pthread_cond_signal(pthread_cond_t *cond);pthread_cond_wait會先解鎖mutex指向的互斥鎖,再將cond指向的條件變量阻塞,直到該條件變量值改變,再將mutex指向的互斥鎖加鎖。
pthread_cond_signal則用來激活一個正在等待條件成立的線程,使該線程繼續運行。與pthread_cond_wait函數配合使用。
使用pthread_cond_wait方式如下:
pthread _mutex_lock(&mutex) while(線程執行的條件是否成立)pthread_cond_wait(&cond, &mutex); 線程執行 pthread_mutex_unlock(&mutex);為什么要在while內判斷呢?
因為在等待運行的程序會有很多,所以需要競爭才能得到下一次運行的權利,而在pthread_cond_signal或者pthread_cond_broadcast執行后,wait雖然成功了,但是當前線程不一定就能競爭到運行的權利,可能被其他更加“強大”的線程搶到手,所以需要不斷循環來判斷是達到了可以執行的條件。
總結
- 上一篇: 进程控制 (二) Others
- 下一篇: 做输卵管造影要注意事项有哪些