生产者与消费者算法的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验六信号量
厦门大学软件学院
吴清强
一.实验目的
⏹加强对进程概念的理解。
⏹进一步了解并发执行的实质。
⏹分析进程争用资源的现象,学习解决进程互斥的方法
⏹了解Linux系统中进程通信的基本原理
二.相关知识
⏹进程的概念。
⏹进程与程序的区别。
⏹进程并发执行的概念。
⏹进程互斥的概念
⏹进程通信的基本原理
三.实验内容
⏹使用信号量实现有限缓冲区的生产者和消费者问题
⏹使用信号量实现读进程具有优先权的读者和写者问题四.实验环境
⏹PC + Linux Red Hat操作系统
⏹GCC
1. 使用信号量实现有限缓冲区的生产
者和消费者问题
一.程序流程图
生产者进程生产流程图
消费者进程消费流程图
二.源代码
1、生产者生产进程函数
DWORD WINAPI Producer(LPVOID lpParameter){
while(true){
for(int j=0;j<4;j++){
if(buffer[j]==0){//找到空缓冲区
if(lock[j]==false){//同步锁为false,可以进行操作
lock[j]=true;//加锁,防止其他线程操作此缓冲区
if(buffer[j]<1){//限定一个缓冲区只能存放一个资源
++buffer[j];//模拟生产资源
cout<<"生产一个资源,放入缓冲区"< lock[j]=false;//解锁 break;//一次生产一个 } } if(j==3){ cout<<"找不到空缓冲区,等待中。。"< Sleep(2000); } } } } return 0; } 2、消费者消费进程函数 DWORD WINAPI Customer(LPVOID lpParameter) { while(true){ for(int n=0;n<4;n++){ if(buffer[n]==1){//找到满缓冲区 if(lock[n]==false){//同步锁为false,可以进行操作 lock[n]=true;//加锁,防止其他线程操作此缓冲区 if(buffer[n]>=1){ --buffer[n];//模拟消费资源 cout<<"消费一个资源,从缓冲区"< lock[n]=false;//解锁 break;//一次生产一个 } } } if(n==3){ cout<<"找不到满缓冲区,等待中。。"< Sleep(2000); }}}} 3、主函数,创建5个进程,其中3个生产者进程,2个消费者进程 int main(int argc,char* argv[]) { HANDLE handle[3]; DWORD dw1,dw2,dw3,dw4,dw5;//创建5个进程 handle[0]=CreateThread(NULL,0,Producer,NULL,0,&dw1); handle[1]=CreateThread(NULL,0,Producer,NULL,0,&dw2); handle[2]=CreateThread(NULL,0,Producer,NULL,0,&dw3); handle[3]=CreateThread(NULL,0,Customer,NULL,0,&dw4); handle[4]=CreateThread(NULL,0,Customer,NULL,0,&dw5); } ·三、试验结果 3个生产者2个消费者,共享4个缓冲区,运行结果如下: 1、一个生产者生产,一个消费者消费: 1、两个生产者连续生产,两个消费者连续消费: 2、多个生产者于多个消费者进行生产消费操作: 2.使用信号量实现读进程具有优先权的 读者和写者问题 . 一、程序流程图 二、源代码 #include #include #include #include #include #include int *critical; int createSem()//创建信号量 { return semget((key_t)1000,2,IPC_CREAT|0600); }//the second parameter in semget is the number of signal we will create void initSignal(int semid,int index,int value)//初始化信号量 { semctl(semid,index,SETV AL,value); } void make_critical () //创建缓冲区 { critical=mmap(NULL,10*sizeof(int),PROT_READ| PROT_WRITE,MAP_SHARED| MAP_ANONYMOUS,-1,0); critical[0]=-1;//the value of the critical file is init as -1 critical[1]=0;//the reader count is 0; } void semWait(int semid,int index)//判断当前进程是否进入缓冲区,被占用就挂起 { struct sembuf sem_buf; sem_buf.sem_num=index; sem_buf.sem_op=-1; sem_buf.sem_flg=SEM_UNDO; semop(semid,&sem_buf,1); } void semSignal(int semid,int index)//唤醒一个在阻塞队列中等待的进程{ struct sembuf sem_buf; sem_buf.sem_num=index; sem_buf.sem_op=1; sem_buf.sem_flg=SEM_UNDO; semop(semid,&sem_buf,1); } //为了让读者优先,当读者获得控制权时,写者进程必须挂起;当第一个读者进程到来(等到写者进程释放控制权)时,第一个读者进程获得优先权,接着其他读者进程不再等待,同时执行。 //故而用critical[1]记录读者进程读到的内容,用semid[0]控制读者或写者进程,用semid[1]更新critical[1]的值 void reader(int semid) { while(1) { semWait(semid,1); critical[1]++; if(critical[1]==1) semWait(semid,0);