linux多線程實驗:模擬售票系統

主要用到函數:linux

#include <pthread.h> pthread_create(&tid[i], nullptr, Sale_ticket, static_cast<void*>(&i));//建立線程
pthread_join(tid[i], nullptr);//等待線程終止
pthread_mutex_t mv_num = PTHREAD_MUTEX_INITIALIZER;//初始化鎖
pthread_mutex_lock(&mv_num);//上鎖
pthread_mutex_unlock(&mv_num);//開鎖
pthread_mutex_destroy(&mv_num);//銷燬鎖
#include <time.h> time_t timep; time (&timep); //獲取系統時間
ctime (&timep); //轉換成字符串
#include <unistd.h> sleep()

 

程序模擬了4個窗口,一塊兒賣20張票。ubuntu

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <unistd.h>
 4 #include <time.h>
 5 #define WINDOW_NUM 4
 6 int total = 20;  7 pthread_mutex_t mv_num = PTHREAD_MUTEX_INITIALIZER;  8 
 9 void* Sale_ticket(void *id) 10 { 11     int Window_id = *static_cast<int*>(id) + 1; 12  time_t timep; 13     time (&timep); 14     printf("Window %d starts saling tickets AT %s", Window_id, ctime(&timep)); 15     while(1) 16  { 17         pthread_mutex_lock(&mv_num); 18         if (total <= 0) { 19             pthread_mutex_unlock(&mv_num); 20             break; 21  } 22         time (&timep); 23         printf("Window %d Sales ticket %d AT %s", Window_id, total--, ctime(&timep)); 24         pthread_mutex_unlock(&mv_num); 25  sleep(Window_id); 26  } 27     return nullptr; 28 } 29 
30 int main() 31 { 32  pthread_t tid[WINDOW_NUM]; 33     int i = 0; 34     for (i = 0; i < WINDOW_NUM; ++i) 35  { 36         pthread_create(&tid[i], nullptr, Sale_ticket, static_cast<void*>(&i)); 37         sleep(1); 38  } 39     for (i = 0; i < WINDOW_NUM; ++i) 40  { 41  pthread_join(tid[i], nullptr); 42  } 43     pthread_mutex_destroy(&mv_num); 44     return 0; 45 }

實驗結果如圖:安全

一些結論:函數

一、網上對linux下sleep()休眠的是整個進程仍是某一個線程的答案不統一,在個人測試環境下(ubuntu 16.04 LTS),發現sleep休眠的是單獨線程。理由:測試

結果中,窗口1每1秒賣一張票,窗口2每2秒賣1張票,主線程每1秒建立一個新窗口,相互之間時間間隔不影響。spa

二、printf線程安全,cout線程不安全。測試發現cout輸出時,線程之間相互干擾打斷。線程

三、ctime (&timep) 轉換過來的字符串,自帶換行符。code

 

---------------------------------------------------------------------------blog

帶補票的售票系統。進程

主要用到條件變量:

#include <pthread.h> pthread_cond_t cv = PTHREAD_COND_INITIALIZER;//初始化條件變量
pthread_cond_wait(&cv, &mv_num);//等待條件變量
pthread_cond_broadcast(&cv); //羣發版的pthread_cond_signal(&cv);
pthread_cond_destroy(&cv);//銷燬一個條件變量

代碼:

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <unistd.h>
 4 #include <time.h>
 5 #define WINDOW_NUM 4
 6 int total = 0;  7 bool flag;  8 pthread_mutex_t mv_num = PTHREAD_MUTEX_INITIALIZER;  9 pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 10 
11 void* Sale_ticket(void *id) 12 { 13     int Window_id = *static_cast<int*>(id) + 1; 14  time_t timep; 15     time (&timep); 16     printf("Window %d starts saling tickets AT %s", Window_id, ctime(&timep)); 17     while(1) 18  { 19         pthread_mutex_lock(&mv_num); 20         while (flag && total <= 0) { 21             pthread_cond_wait(&cv, &mv_num); 22  } 23         if (total <= 0) { 24             pthread_mutex_unlock(&mv_num); 25             break; 26  } 27         time (&timep); 28         printf("Window %d Sales ticket %d AT %s", Window_id, total--, ctime(&timep)); 29         pthread_mutex_unlock(&mv_num); 30  sleep(Window_id); 31  } 32     return nullptr; 33 } 34 
35 int main() 36 { 37  pthread_t tid[WINDOW_NUM]; 38     int i = 0; 39     int k = 2; 40     flag = true; 41     for (i = 0; i < WINDOW_NUM; ++i) 42  { 43         pthread_create(&tid[i], nullptr, Sale_ticket, static_cast<void*>(&i)); 44         sleep(1); 45  } 46     while (k--) { 47         sleep(10); 48         pthread_mutex_lock(&mv_num); 49         total += 10; 50  time_t timep; 51         time (&timep); 52         printf("*********Add 10 tickets*********** AT %s", ctime(&timep)); 53         pthread_cond_broadcast(&cv); 54         pthread_mutex_unlock(&mv_num); 55  } 56     flag = false; 57     for (i = 0; i < WINDOW_NUM; ++i) 58  { 59  pthread_join(tid[i], nullptr); 60  } 61     pthread_mutex_destroy(&mv_num); 62     pthread_cond_destroy(&cv); 63     return 0; 64 }

結果:

討論:

主要是關於

while (flag && total <= 0) { pthread_cond_wait(&cv, &mv_num); }

這裏用的是while而不是if。while相比if,可能在效率上不高,可是保證了穩定和安全。網上有不少解釋。

主要是兩個緣由:(1)it was not interrupted; (2)due to spurious wakeup.

第一點說的是一些中斷或者非人爲因素而致使的返回信號沒被正確接受。

第二點說的就是傳說中的「驚羣效應」。

相關文章
相關標籤/搜索