linux多线程实验:模拟售票系统

时间:2022-12-29 19:43:28

主要用到函数:

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

实验结果如图:

linux多线程实验:模拟售票系统

一些结论:

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 }

结果:

linux多线程实验:模拟售票系统

讨论:

主要是关于

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

这里用的是while而不是if。while相比if,可能在效率上不高,但是保证了稳定和安全。网上有很多解释。

主要是两个原因:(1)it was not interrupted; (2)due to spurious wakeup.

第一点说的是一些中断或者非人为因素而导致的返回信号没被正确接受。

第二点说的就是传说中的“惊群效应”。