linux 線程同步

最近看《UNIX環境高級編程》多線程同步,看到他舉例說條件變量pthread_cond_t怎麼用,愣是沒有看懂,只好在網上找了份代碼,跑了跑,才弄明白

  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/
  5. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化條件變量*/
  6. void *thread1(void *);
  7. void *thread2(void *);
  8. int i=1;
  9. int main(void)
  10. {
  11. pthread_t t_a;
  12. pthread_t t_b;
  13. pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創建進程t_a*/
  14. pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創建進程t_b*/
  15. pthread_join(t_a, NULL);/*等待進程t_a結束*/
  16. pthread_join(t_b, NULL);/*等待進程t_b結束*/
  17. pthread_mutex_destroy(&mutex);
  18. pthread_cond_destroy(&cond);
  19. exit(0);
  20. }
  21. void *thread1(void *junk)
  22. {
  23. for(i=1;i<=6;i++)
  24. {
  25. pthread_mutex_lock(&mutex);/*鎖住互斥量*/
  26. printf("thread1: lock %d/n", __LINE__);
  27. if(i%3==0){
  28. printf("thread1:signal 1 %d/n", __LINE__);
  29. pthread_cond_signal(&cond);/*條件改變,發送信號,通知t_b進程*/
  30. printf("thread1:signal 2 %d/n", __LINE__);
  31. sleep(1);
  32. }
  33. pthread_mutex_unlock(&mutex);/*解鎖互斥量*/
  34. printf("thread1: unlock %d/n/n", __LINE__);
  35. sleep(1);
  36. }
  37. }
  38. void *thread2(void *junk)
  39. {
  40. while(i<6)
  41. {
  42. pthread_mutex_lock(&mutex);
  43. printf("thread2: lock %d/n", __LINE__);
  44. if(i%3!=0){
  45. printf("thread2: wait 1 %d/n", __LINE__);
  46. pthread_cond_wait(&cond,&mutex);/*解鎖mutex,並等待cond改變*/
  47. printf("thread2: wait 2 %d/n", __LINE__);
  48. }
  49. pthread_mutex_unlock(&mutex);
  50. printf("thread2: unlock %d/n/n", __LINE__);
  51. sleep(1);
  52. }
  53. }
  1. #include <pthread.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/  
  5. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化條件變量*/  
  6. void *thread1(void *);  
  7. void *thread2(void *);  
  8. int i=1;  
  9. int main(void)  
  10. {  
  11.     pthread_t t_a;  
  12.     pthread_t t_b;  
  13.     pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創建進程t_a*/  
  14.     pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創建進程t_b*/  
  15.     pthread_join(t_a, NULL);/*等待進程t_a結束*/  
  16.     pthread_join(t_b, NULL);/*等待進程t_b結束*/  
  17.     pthread_mutex_destroy(&mutex);  
  18.     pthread_cond_destroy(&cond);  
  19.     exit(0);  
  20. }  
  21. void *thread1(void *junk)  
  22. {  
  23.     for(i=1;i<=6;i++)  
  24.     {  
  25.         pthread_mutex_lock(&mutex);/*鎖住互斥量*/  
  26.         printf("thread1: lock %d/n", __LINE__);  
  27.         if(i%3==0){  
  28.             printf("thread1:signal 1  %d/n", __LINE__);  
  29.             pthread_cond_signal(&cond);/*條件改變,發送信號,通知t_b進程*/  
  30.             printf("thread1:signal 2  %d/n", __LINE__);  
  31.             sleep(1);  
  32.         }  
  33.         pthread_mutex_unlock(&mutex);/*解鎖互斥量*/  
  34.         printf("thread1: unlock %d/n/n", __LINE__);  
  35.         sleep(1);  
  36.     }  
  37. }  
  38. void *thread2(void *junk)  
  39. {  
  40.     while(i<6)  
  41.     {  
  42.         pthread_mutex_lock(&mutex);  
  43.         printf("thread2: lock %d/n", __LINE__);  
  44.         if(i%3!=0){  
  45.             printf("thread2: wait 1  %d/n", __LINE__);  
  46.             pthread_cond_wait(&cond,&mutex);/*解鎖mutex,並等待cond改變*/  
  47.             printf("thread2: wait 2  %d/n", __LINE__);  
  48.         }  
  49.         pthread_mutex_unlock(&mutex);  
  50.         printf("thread2: unlock %d/n/n", __LINE__);  
  51.         sleep(1);  
  52.     }  
  53. }  

編譯:

[X61@horizon threads]$ gcc thread_cond.c -lpthread -o tcd

以下是程序運行結果:

[X61@horizon threads]$ ./tcd 
thread1: lock 30
thread1: unlock 40

thread2: lock 52
thread2: wait 1 55
thread1: lock 30
thread1: unlock 40

thread1: lock 30
thread1:signal 1 33
thread1:signal 2 35
thread1: unlock 40

thread2: wait 2 57
thread2: unlock 61

thread1: lock 30
thread1: unlock 40

thread2: lock 52
thread2: wait 1 55
thread1: lock 30
thread1: unlock 40

thread1: lock 30
thread1:signal 1 33
thread1:signal 2 35
thread1: unlock 40

thread2: wait 2 57
thread2: unlock 61

這裏的兩個關鍵函數就在pthread_cond_wait和pthread_cond_signal函數。

本例中:

線程一先執行,獲得mutex鎖,打印,然後釋放mutex鎖,然後阻塞自己1秒。

線程二此時和線程一應該是併發的執行
 ,這裏是一個要點,爲什麼說是線程此時是併發的執行,因爲此時不做任何干涉的話,是沒有辦法確定是線程一先獲得執行還是線程二先獲得執行,到底那個線程先獲得執行,取決於操作系統的調度,想刻意的讓線程2先執行,可以讓線程2一出來,先sleep一秒。
這裏併發執行的情況是,線程一先進入循環,然後獲得鎖,此時估計線程二執行,阻塞在
pthread_mutex_lock(&mutex);
這行語句中,直到線程1釋放mutex鎖
pthread_mutex_unlock(&mutex);/*解鎖互斥量*/
然後線程二得已執行,獲取metux鎖,滿足if條件,到pthread_cond_wait (&cond,&mutex);/*等待*/
這裏的線程二阻塞,不僅僅是等待cond變量發生改變,同時釋放mutex鎖 ,因爲當時看書沒有注意,所以這裏卡了很久。
mutex鎖釋放後,線程1終於獲得了mutex鎖,得已繼續運行,當線程1的if(i%3==0)的條件滿足後,通過pthread_cond_signal發送信號,告訴等待cond的變量的線程(這個情景中是線程二),cond條件變量已經發生了改變。

不過此時線程二並沒有立即得到運行 ,因爲線程二還在等待mutex鎖的釋放,所以線程一繼續往下走,直到線程一釋放mutex鎖,線程二才能停止等待,打印語句,然後往下走通過pthread_mutex_unlock(&mutex)釋放mutex鎖,進入下一個循環。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章