运行结果
流程图
废话不多说,直接上代码
1 #include<iostream>
2 #include <string>
3 #include <unistd.h> //sleep函数库文件
4 #include<process.h>
5 #include<windows.h>//句多线程柄库文件
6 #define n 10 //缓冲区大小
7 #define sleepTime 2 //控制生产者消费者的生产和消费速度,便于演示观察
8 #define executime 3000//模拟生产消费者算法的时间长
9 using namespace std;
10
11 typedef HANDLE semaphore; //互斥信号量句柄
12 typedef int item; //缓冲池中产品类型
13
14 item buffer[n] = {0}; //定义缓冲池,并全部置空
15 int in = 0;
16 int out = 0;
17 int counter = 0;//每当生产者进程向缓冲池中投放(或取走)一个产品后,使counter加1(或减1)。
18 semaphore mutex , empty , full ;//定义互斥信号量句柄
19
20 //模拟算法中涉及的课外知识
21
22 //HANDLE WINAPI CreateSemaphore( _In_opt_LPSECURITY_ATTRIBUTES lpSemaphoreAttributes ,_In_LONG lInitialCount, _In_ LONG lMaximumCount,_In_opt_? LPCTSTR lpName
23 //);
24 //第一个参数:安全属性,如果为NULL则是默认安全属性
25 //第二个参数:信号量的初始值,要>=0且<=第三个参数
26 //第三个参数:信号量的最大值
27 //第四个参数:信号量的名称
28 //
29 //返回值:指向信号量的句柄,如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄
30 //
31 //DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
32 //
33 //第一个参数:等待对象的 handle(代表一个核心对象)。
34 //第二个参数:等待的最长时间。时间终了,即使 handle尚未成为激发状态,此函数也要返回。此值可以是0(代表立刻返回),也可以是 INFINITE代表无穷等待。
35 //
36 //BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore,_In_ LONG lReleaseCount,_Out_opt_ LPLONG lpPreviousCount);
37 //第一个参数:信号量句柄
38 //第二个参数:释放后,信号量增加的数目
39 //第三个参数:信号量增加前的值存放的地址,如果不需要则为NULL
40 //返回值:释放是否成功
41 //void wait(semaphore &S)
42 //{
43 // while (S<=0);
44 // S=S-1;
45 //}
46 //
47 //void signal(semaphore &S)
48 //{
49 // S=S+1;
50 //}
51 //
52
53 void display(string str)
54 {
55 cout<<str<<endl;
56 cout<<"缓冲池:";
57 for(int i=0;i<n;i++){
58 cout<<buffer[i]<<' ';
59 // sleep(1); 减慢输出速度
60 }
61 cout<<endl;
62 cout<<"counter:"<<counter<<endl<<endl;
63 //cout<<" mutex:"<<mutex<<" empty:"<<empty<<" full:"<<full<<endl<<endl; 由于是互斥信号量句柄,无法直接访问其值
64 }
65
66 unsigned __stdcall producer(void*)
67 {
68 do{
69 WaitForSingleObject(empty, INFINITE);//等待同步信号量empty
70 WaitForSingleObject(mutex, INFINITE);//等待互斥信号量mutex
71 item nextp=1;
72 buffer[in]=nextp;
73 in=(in+1)%n;
74 counter++;
75 display("生产一件产品");
76
77 sleep(sleepTime);
78 ReleaseSemaphore(mutex, 1, NULL);//释放互斥信号量mutex
79 ReleaseSemaphore(full, 1, NULL);//释放同步信号量full
80
81 }while(1);
82 return 1;
83 }
84
85 unsigned __stdcall consumer(void* )
86 {
87 do{
88 WaitForSingleObject(full, INFINITE);//等待同步信号量full
89 WaitForSingleObject(mutex, INFINITE);//等待互斥信号量mutex
90 item nextc=buffer[out];
91 buffer[out]=0;
92 out=(out+1)%n;
93 counter--;
94 sleep(sleepTime);
95 display("消费一件产品");
96 ReleaseSemaphore(mutex, 1, NULL);//释放互斥信号量mutex
97 ReleaseSemaphore(empty, 1, NULL);//释放信号量
98 }while(1);
99 return 2;
100 }
101
102 int main(){
103 int buf_max=n;//输入缓冲区大小,整形变量,大于0,建议在10—20之间一个整数 ,这里为定义的宏n
104 int producerNum; //输入生产者数量,整形变量,建议在4-8,直接,否则太大电脑跑不动,太小生产速度不够
105 int consumerNum;//输入消费者数量,整形变量,建议小于生产者数量,不要为 0
106 cout<<"请输入生产者数量:";cin>>producerNum;
107 cout<<"请输入消费者数量:";cin>>consumerNum;
108 empty = CreateSemaphore(NULL, buf_max, buf_max, NULL); //初值为缓冲池大小,最大为缓冲池大小
109 full = CreateSemaphore(NULL, 0, buf_max, NULL); //初值为0,最大为缓冲池大小
110 mutex = CreateSemaphore(NULL,1,1,NULL); //初值为1,最大为1
111 HANDLE hthproducer[producerNum], htconsumer[consumerNum];//定义生产者 消费者线程句柄池大小
112
113 //创建线程
114 int i;
115
116 for(i=0;i<producerNum;i++)
117 {
118 hthproducer[i] = (HANDLE)_beginthreadex(NULL, 0, producer, NULL, 0, NULL);//生产者线程
119 }
120
121 for(i=0;i<consumerNum;i++)
122 {
123 htconsumer[i] = (HANDLE)_beginthreadex(NULL, 0, consumer, NULL, 0, NULL);//消费者线程
124 }
125
126
127
128 //等待子线程结束
129 for(i=0;i<producerNum;i++)
130 WaitForSingleObject(hthproducer[i], executime);//在时间executime到达后无论是否激活线程,都会关闭线程
131 for(i=0;i<consumerNum;i++)
132 WaitForSingleObject(htconsumer[i], executime);//在时间executime到达后无论是否激活线程,都会关闭线程
133
134 //关闭句柄
135 for(i=0;i<producerNum;i++)
136 CloseHandle(hthproducer[i]);
137 for(i=0;i<consumerNum;i++)
138 CloseHandle(htconsumer[i]);
139
140 CloseHandle(empty);
141 CloseHandle(full);
142 CloseHandle(mutex);
143
144 cout<<"演示完毕,谢谢观看";
145
146
147 return 0;
148 }