问题一:
生产者------消费者问题
分析:该问题的基本工作模式为:
如果缓冲区为空则消费者不能取;如果缓冲区为满则生产者不可以继续生产。
如果缓冲区曼,需要唤醒消费者;如果缓冲区为空则需要唤醒生产者
N个缓冲区;
如果只有一个信号量empty时,则:empty = N,in表示生产者放入缓冲区的商品的个数、out表示消费者取出商品个数.in、out为共享变量。因此为了防止多个进程同时修改它们,将对他们的操作放在PV操作中。
Producer:
p(empty)
//如果empty==0,则生产者进程自我阻塞。
p(mutex)
in:=in+1;
v(mutex)
Consumer:
v(empty)
p(mutex)
out:=out+1;
v(mutex)
小结:以上程序缺少了唤醒操作。因此引入多个信号量。用于唤醒阻塞的进程。
Producer:
p(empty) //如果empty==0,则生产者进程自我阻塞。
p(mutex)
in:=in+1 mod N;
v(mutex)
v(full)
Consumer:
p(full)
p(mutex)
out:=out+1 mod N;
v(mutex)
v(empty)
对于in、out取余的原因是为了用于循环。
实现程序--------(锁和PV信号量)
local.c 文件- #ifndef _LOCAL_H
- #define _LOCAL_H
- #include<pthread.h>
- #include<unistd.h>
- #include<stdio.h>
- #include<sys/types.h>
- #include<sys/ipc.h>
- #include<sys/msg.h>
- #include<sys/sem.h>
- union semun {
- int val;
- struct semid_ds *buf;
- ushort *array;
- };
- typedef struct MES{
- int num;
- int sem1[5];//该程序只使用了两个信号集
- }MES;
- #define BUFF 3
- pthread_mutex_t mutex;
- struct sembuf sbuf1={0,-1,IPC_NOWAIT};
- struct sembuf sbuf2={0,1,IPC_NOWAIT};
- //信号在信号集中的索引、操作类型(释放或归还)、是否阻塞
- void *Producer_pthread(void *mes);
- void *Consumer_pthread(void *mes);
- int create_semaphore(char * path, int number, char c,union semun* sem);
- //创建了两个信号量集,empty为第一个、full为第二个
- #endif
文件:producer_constum.c
- #include"local.h"
- int create_semaphore(char * path, int number, char c,union semun* sem)
- {
- //如果number>0,表示empty信号量。
- //如果number = 0,表示full信号量。
- key_t key;
- int semid;
- if((key = ftok(path,c))==-1) {
- perror("ftok error\n");
- return -1;
- }
- if((semid= semget(key,1,IPC_CREAT|0666))==-1) {
- perror("segmet error\n");
- return -1;
- }
- sem->val= number;
- if(semctl(semid,0,SETVAL,sem)==-1){
- perror("semctl error\n");
- return -1;
- }
- return semid;
- }
-
- void* Consumer_pthread(void *mes)
- {
- int i =0;
- while(i<10) {
- semop(((MES*)mes)->sem1[1],&sbuf1,1);
- pthread_mutex_lock(&mutex);
- sleep(1);
- printf("cumsumer: out = %d \n",((MES*)mes)->num+1);
- ((MES*)mes)->num = (((MES*)mes)->num+1)%BUFF;
- pthread_mutex_unlock(&mutex);
- semop(((MES*)mes)->sem1[0],&sbuf2,1);
- i++;
- sleep(1);
- }
- return NULL;
- }
- void* Producer_pthread(void *mes)
- {
- int i=0;
- while(i<10) {
- semop(((MES*)mes)->sem1[0],&sbuf1,1);
- pthread_mutex_lock(&mutex);
- printf("producer: in = %d \n",((MES*)mes)->num+1);
- sleep(1);
- ((MES*)mes)->num =(((MES*)mes)->num+1)%BUFF;
- pthread_mutex_unlock(&mutex);
- sleep(1);
- printf("wakeup consumer\n");
- semop(((MES*)mes)->sem1[1],&sbuf2,1);
- i++;
- }
- return NULL;
- }
- int main()
- {
- pthread_t produce , consume;
- MES mes1,mes2;
- union semun semopts1,semopts2 ;
- pthread_mutex_init(&mutex,NULL);//建立具有默认值属性的
- mes1.num= 0;
- mes1.sem1[0]=create_semaphore(".", BUFF, 's',&semopts1);
- mes1.sem1[1]=create_semaphore(".", 0, 'k',&semopts2);
- mes2 = mes1;
- if( pthread_create(&produce,NULL,Producer_pthread,(void*)&mes1)==-1)
- printf("produce ceate fail\n");
- if( pthread_create(&consume,NULL,Consumer_pthread,(void*)&mes2)==-1)
- printf("consume create fail\n");
- pthread_join(produce,NULL);
- pthread_join(consume,NULL);
- pthread_mutex_destroy(&mutex);
- return 0;
- }
问题二:
读者-----------写者问题
(以缓冲区为媒介,实现读者和写者的交互)
分析:
该问题的工作原则:如果缓冲区为空时,读者不能访问缓冲区并且需要唤醒写者
如果缓冲区为满时,写者不能将信息写入缓冲区且需要唤醒读者
如果读者此时占有缓冲区,那么只允许读者进程访问该缓冲区
如果写者进程占有缓冲区,那么不允许其他进程访问该缓冲区(其他进程包括:读者进程和别的写者进程)
由上面分析到需要下面的变量:
wm=1 rm = 1 counter = 0
(共享变量)
实现:
reader :
if(counter
>=0)//读者进来,则阻塞写者进程
p(wm);
p(rm)
counter +=1;
v(rm)
读
p(rm)//读者读完离开
counter -=1;
v(rm)
if(count==0)
v(wm);此时无读者进程,将写者进程唤醒。让读者和写者进程同时竞争资源
write :
p(rm)
p(wm)
写
v(wm)
v(rm)
上面分析得因为写者进程和读者进程不可以并发执行
,因此需要阻塞读者进程,因此会想到对rm信号量进行pv操作,但是如果要看能否运行写者进程的大前提已经在读者进程中实现了,因为只有counter=0时,才会唤醒写者进程。
只需要:
p(wm)
写
v(wm)
代码实现-----------------(锁、条件变量)
local_cond.h 文件
- #ifndef _LOCAL_COND_H
- #define _LOCAL_COND_H
- #include<stdio.h>
- #include<pthread.h>
- #include<unistd.h>
- pthread_mutex_t rm ,wm;
- pthread_cond_t cond;
- void * Reader(void *counter);
- void * Writer(void*arg);
- #endif
reader_writer.c文件
- #include"local_cond.h"
- void * Reader(void * counter)
- {
- while(1) {
- if(*((int*)counter) >=0)
- pthread_mutex_lock(&wm);
- pthread_mutex_lock(&rm);
- pthread_cond_wait(&cond,&wm);
- (*(int*)counter) +=1;
- printf("reader is reading\n");
- printf("Reader := %d\n",(*(int*)counter));
- pthread_mutex_unlock(&rm);
-
- pthread_mutex_lock(&rm);
- printf("reader left \n");
- (*(int*)counter) -=1;
- printf("Reader := %d\n",(*(int*)counter));
- pthread_cond_wait(&cond,&wm);
- pthread_mutex_unlock(&rm);
- if((*(int*)counter)==0)
- pthread_mutex_unlock(&wm);
- sleep(1);
- }
- return NULL;
- }
- void* Writer(void *arg)
- {
- while(1) {
- pthread_mutex_lock(&wm);
- pthread_cond_wait(&cond,&wm);
- printf("Writer is writing\n");
- pthread_mutex_unlock(&wm);
- pthread_cond_signal(&cond);
- sleep(1);
- }
- return NULL;
- }
- int main()
- {
- pthread_t reader,writer;
- int counter = 0;
- pthread_mutex_init(&rm,NULL);
- pthread_mutex_init(&wm,NULL);
- pthread_cond_init(&cond,NULL);
-
- pthread_create(&writer,NULL,(void*)Writer,NULL);
- pthread_create(&reader,NULL,(void*)Reader,(void*)&counter);
- do{
- pthread_cond_signal(&cond);
- }while(1);
- pthread_join(writer,NULL);
- pthread_join(reader,NULL);
- pthread_mutex_destory(&rm);
- pthread_mutex_destory(&wm);
- pthread_cond_destory(&cond);
- return 0;
- }
阅读(281) | 评论(0) | 转发(0) |