📄 3.txt
字号:
一个生产者一个消费者进程,使用轮换法使这两个进程轮换执行。
#include <windows>
#include <stdlib>
#include <iostream>
#include <conio>
using namespace std;
#define MAX_SIZE 200
char buffer[MAX_SIZE];
int in=0;
int out=0;
int counter=0;
int inUse=0;
DWORD WINAPI Producer(LPVOID);
DWORD WINAPI Consumer(LPVOID);
int main()
{
HANDLE hTrd;
DWORD ThreadId;
hTrd=CreateThread(NULL,0,Producer,(LPVOID)('A'),0,&TreadId);
if(hTrd)
{
cout << "thread function " << 'a' <<" Lunched"<<endl;
}
hTrd=CreateThread(NULL,0,Consumer,NULL,0,&TreadId);
Sleep(2000);
getch();
return 0;
}
DWORD WINAPI Producer(LPVOID m)
{
while(1)
{
if(inUse==0)
{
buffer[in++]=(char)m;
in%=MAX_SIZE;
cout << "in" << (char)m << endl;
inUse=1;//(1)
}
//(1)
}
}
DWORD WINAPI Producer(LPVOID m)
{
char m;
while(1)
{
if(inUse==1)
{
m=buffer[out++];
out%=MAX_SIZE;
cout << in << out << counter << inUse << endl;
inUse=0;//(2)
}
//(2)
}
}
这样写的程序可以保证两个进程轮换执行,可是如果把两个进程中对inUse变量的修改放到另一个位置就不能实现这个功能。例如将inUse=1;//(1)放在//(1)的位置,就不能保证轮换执行,消费进程能多次进入buffer。请各位帮我看一下为什么会这样?
例如将inUse=1;//(1)放在//(1)的位置,就不能保证轮换执行,消费进程能多次进入buffer。请各位帮我看一下为什么会这样?
----------------------------------------
做这样的改变后,Producer每次检查inUse,无论是否成功,他都会将inUse设置为1,那么考虑这样的情况: Producer执行完对inUse的检测(失败,此时Consumer在if语句块内),然后系统调度Consumer,等到Consumer执行完inUse=0;然后系统调度Producer,Producer执行inUse=1;,此时Producer将继续检测失败,而Consumer可以继续执行if语句块的内容
哦,有些明白了。在Producer中的if(inUse==0)应该汇编成两条语句,一条是判断inUse==0,一条是跳转到inUse=1;(在失败的情况下)。如果Producer正好执行完判断语句,正要执行跳转语句时时间片到,那么开始执行consumer,Consumer执行完inUse=0,后自己进入判断,知道时间片结束。然后Producer执行inUse=1,这样Producer又进入等待,而Consumer就满足条件继续进行。
这样是不是因为inUse也是一个临界资源,应该放到临界区中去?
谢谢fflush的解答
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -