并发程序的同步和互斥.docx
- 文档编号:23416236
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:16
- 大小:47.23KB
并发程序的同步和互斥.docx
《并发程序的同步和互斥.docx》由会员分享,可在线阅读,更多相关《并发程序的同步和互斥.docx(16页珍藏版)》请在冰豆网上搜索。
并发程序的同步和互斥
并发程序的同步和互斥
一、选择题目
生产者-消费者问题
二、提交程序说明
创建共享区程序文档:
share.c
生产者程序文档:
producer.c
消费者程序文档:
consumer.c
编译要求:
使用make命令编译以上三个文件,然后先用./执行share,再执行后两个,如果需要多个生产者或消费者,可以多运行几个producer或consumer。
三、程序设计要点说明
关键数据结构的定义
1,缓存区的数据结构,包括一个整型数组和两个int类型的参数。
structArray{
inta[MAX];
inthead;//表示循环数组的头部
inttail;//表示循环数组的尾部
}
2,创建共享存储区
structArray*shmptr;;
shmid=shmget(MY_SHMKEY,sizeof(structArray),IPC_CREAT|IPC_E
XCL|0666);//建立一个共享存储区
semid=semget(MY_SEMKEY,3,IPC_CREAT|0666);//建立一个信号量集
shmptr=(structArray*)shmat(shmid,0,0);//把一个共享存储区附接到进程内存空间
(*shmptr).head=0;
(*shmptr).tail=0;
3,操纵一个信号量集,包括赋初值
semval=1;
semctl(semid,0,SETVAL,semval);//编码为0的信号量,初值为1(mutex)
semval=3;
semctl(semid,1,SETVAL,semval);//编码为1的信号量,初值为3(empty)
semval=0;
semctl(semid,2,SETVAL,semval);//编码为2的信号量,初值为0(full)
4,获得共享存储区
shmid=shmget(MY_SHMKEY,sizeof(structArray),0666);//获得共享存储区首地址
semid=semget(MY_SEMKEY,3,0666);//跟信号量集,建立联系0:
mutex1:
empty2:
full
5,一个wait操作
semopbuf.sem_num=1;//编号为1的信号量,判断是否满wait(empty)
semopbuf.sem_op=-1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
总体执行逻辑设计
利用一个进程创建共享存储区,打开另一个进程作为生产者,生产者先判断缓冲池是否已满,若满,则阻塞;若不满再看是否有互斥进程。
再打开第三个文件进程作为消费者,消费者先判断缓冲池是否为空,若空,则阻塞;若不空再看是否有互斥进程。
执行参数设定
只需执行一次第一个文件,其他两个文件执行几次就是几个消费者或生产者。
共享存储区数组的长度为3。
四、竞态条件分析
正确的执行结果:
条件:
1三个信号量mutex,empty,full,初始值分别为1,3,0,
2一个共享存储区,大小为3的数组
3作为生产者
先wait(empty)再wait(mutex)进行判断
然后进行生产,同时数组头指针加1取模
Signal(mutex),signal(full)
4作为消费者
先wait(full)再wait(mutex)进行判断
然后进行生产,同时数组尾指针加1取模
Signal(mutex),signal(emptyl)
1,生产者循环生产1--9,然后将物品放置在一个缓冲区中供消费者消费。
消费者从缓冲区中获得物品,然后释放缓冲区。
(一个生产者,两个消费者)
2,当生产者生产物品时,如果没有空缓冲区可用,那么生产者必须等待消费者释放出一个空缓冲区后才能继续生产。
此时没有消费者,生产者阻塞
3,当消费者消费物品时,如果缓冲区空了,那么消费者将被阻塞,直到新的物品被生产出来。
此时没有生产者,消费者阻塞
没有同步制约:
条件:
将正确代码中生产者的wait(empty),signal(full)注释掉,同时将消费者的wait(full),signal(empty)注释掉。
1当生产者生产物品时,即使没有空缓冲区可用,生产者仍能继续生产。
此时没有消费者,生产者可一直生产
2当消费者消费物品时,即使缓冲区空了,消费者仍能消费。
此时没有生产者,可消费者一直在消费
没有互斥制约:
1,几个消费者也可同时从一个缓冲区消费东西。
条件:
将消费者的wait(mutex),signal(mutex)注释掉
2,几个生产者可以同时向一个空缓冲区生产东西;
条件:
将生产者的wait(mutex),signal(mutex)注释掉
(一个生产者,两个消费者)两个消费者都消费了2,但只生产了一个2.
五、编程平台说明
1,并发程序编写平台:
Linux下的进程级别并发。
2,同步机制:
整型信号量机制。
六、执行结果及分析
1没有采用同步机制进行协调情况下的执行结果
一个生产者,两个消费者
两个消费者都消费了2,但只生产了一个2.,4没有被消费,但没有了。
因为进程没有互斥制约条件,消费者1发现产品2可以消费,同时消费者2也发现了产品2可以消费,于是都消费了2,同时两个的指针各加了1,跳过了一个产品4。
此时没有消费者,生产者可一直生产,因为进程没有同步制约条件
此时没有生产者,可消费者一直在消费,因为进程没有同步制约条件
2采用同步机制进行协调时的执行结果。
生产者循环生产1--9,然后将物品放置在一个缓冲区中供消费者消费。
消费者从缓冲区中获得物品,然后释放缓冲区。
原因:
采用了互斥制约条件,消费者不能同时消费同一件产品。
(一个生产者,两个消费者)
此时没有消费者,生产者阻塞。
采用了同步互斥制约关系,缓冲池满了后,生产者不再生产。
此时没有生产者,消费者阻塞。
采用了同步互斥制约关系,缓冲池空了后,消费者不再消费。
1,Share.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMY_SHMKEY123//needtochange
#defineMY_SEMKEY123//needtochange
#defineMAX3
structArray{
inta[MAX];
inthead;
inttail;
};
voidsigend(int);
intshmid,semid;
intmain(void)
{
structArray*shmptr;
intsemval;
structsembufsemopbuf;
shmid=shmget(MY_SHMKEY,sizeof(structArray),IPC_CREAT|IPC_EXCL|0666);//建立一个共享存储区
semid=semget(MY_SEMKEY,3,IPC_CREAT|0666);//建立一个信号量集
shmptr=(structArray*)shmat(shmid,0,0);//把一个共享存储区附接到进程内存空间
(*shmptr).head=0;
(*shmptr).tail=0;
//操纵一个信号量集,包括赋初值
semval=1;
semctl(semid,0,SETVAL,semval);
semval=3;
semctl(semid,1,SETVAL,semval);
semval=0;
semctl(semid,2,SETVAL,semval);
signal(SIGINT,sigend);//设置对信号的处理方式或处理过程
signal(SIGTERM,sigend);
sleep(100000);
}
voidsigend(intsig)
{
shmctl(shmid,IPC_RMID,0);
semctl(semid,IPC_RMID,0);
exit(0);
}
2,producer.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMY_SHMKEY123//needtochange
#defineMY_SEMKEY123//needtochange
#defineMAX3
structArray{
inta[MAX];
inthead;
inttail;
};
intshmid,semid;
intmain(void)
{
structArray*shmptr;
inti;
structsembufsemopbuf;
shmid=shmget(MY_SHMKEY,sizeof(structArray),0666);//获得共享存储区首地址
semid=semget(MY_SEMKEY,3,0666);//跟信号量集,建立联系0:
mutex1:
empty2:
full
shmptr=(structArray*)shmat(shmid,0,0);//把一个共享存储区附接到进程内存空间
printf("Actasproducer.\n\n");
while
(1){
for(i=1;i<10;i++){
semopbuf.sem_num=1;//判断是否满wait(empty)
semopbuf.sem_op=-1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
semopbuf.sem_num=0;//判断互斥wait(mutex)
semopbuf.sem_op=-1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
printf("produce:
%d\n",i);
(*shmptr).a[(*shmptr).head]=i;
sleep(3);
(*shmptr).head=((*shmptr).head+1)%MAX;
semopbuf.sem_num=0;//signal(mutex)
semopbuf.sem_op=1;//signal(full)
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
semopbuf.sem_num=2;
semopbuf.sem_op=1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
}
}
}
3,consumer.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMY_SHMKEY123//needtochange
#defineMY_SEMKEY123//needtochange
#defineMAX3
structArray{
inta[MAX];
inthead;
inttail;
};
intshmid,semid;
intmain(void)
{
structArray*shmptr;
inti;
structsembufsemopbuf;
shmid=shmget(MY_SHMKEY,sizeof(structArray),0666);//获得共享存储区首地址
semid=semget(MY_SEMKEY,3,0666);//跟信号量集,建立联系0:
mutex1:
empty2:
full
shmptr=(structArray*)shmat(shmid,0,0);//把一个共享存储区附接到进程内存空间
printf("Actasproducer.\n\n");
while
(1){
for(i=1;i<10;i++){
semopbuf.sem_num=1;//判断是否满wait(empty)
semopbuf.sem_op=-1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
semopbuf.sem_num=0;//判断互斥wait(mutex)
semopbuf.sem_op=-1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
printf("produce:
%d\n",i);
(*shmptr).a[(*shmptr).head]=i;
sleep(3);
(*shmptr).head=((*shmptr).head+1)%MAX;
semopbuf.sem_num=0;//signal(mutex)
semopbuf.sem_op=1;//signal(full)
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
semopbuf.sem_num=2;
semopbuf.sem_op=1;
semopbuf.sem_flg=SEM_UNDO;
semop(semid,&semopbuf,1);
}
}
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 并发 程序 同步