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張票。

 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 }

實驗結果如圖:

一些結論:

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

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

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

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

 

---------------------------------------------------------------------------

帶補票的售票系統。

主要用到條件變量:

#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.

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

第二點說的就是傳說中的“驚群效應”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM