生产者-消费者问题的代码实现

两种实现的代码思路,第一种是将对商品和货架的两个操作定义为一个原子操作,然后生产者和消费者去分别实现不同的操作。另一种是把对商品和货架的操作定义为两个原子操作,但是要注意PV操作的顺序

计数信号量,一个原子操作

//计数信号量
#include <head.h>

int main(int argc, char **argv) {
    int ret = 0;
    //创建信号量
    int semid = semget(3000, 2, IPC_CREAT|0666);
    ERROR_CHECK(semid, -1, "semget");

    //创建unsigned short数组来SETALL
    unsigned short arr[2] = {0, 5};//商品0,5货架5
    semctl(semid, 0, SETALL, arr);  //0表示对全部信号量操作
	
    //信号量的操作函数,数组一次实现两个原子操作
    struct sembuf sop[2];
    memset(sop, 0, sizeof(sop));

    //父进程:生产者,生产商品,消耗货架
    if(fork()){ 
        sop[0].sem_num = 0;  //对信号量0操作,即商品  
        sop[0].sem_op = 1;  //生产商品
        sop[0].sem_flg = 0;

        sop[1].sem_num = 1;  //对信号量1操作,即货架
        sop[1].sem_op = -1;  //消耗商品
        sop[1].sem_flg = 0;
        while(1){
            //一个原子操作
            ret = semop(semid, sop, 2);
            ERROR_CHECK(ret, -1, "semop1");
		   //GETVAL直接返回信号代表的资源数量
            printf("生产者:商品的数量 = %d, 货架的数量 = %d\n",
            semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
            sleep(1);
        }
    }

    else{
        //子进程:消费者,消耗商品,释放货架
        sop[0].sem_num = 0;
        sop[0].sem_op = -1;
        sop[0].sem_flg = 0;
        
        sop[1].sem_num = 1;
        sop[1].sem_op = 1;
        sop[1].sem_flg = 0;

        while(1){
            ret = semop(semid, sop, 2);
            ERROR_CHECK(ret, -1, "semop2");

            printf("消费者:商品的数量 = %d, 货架的数量 = %d\n", 			   semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
            sleep(2);
        }
    }
    return 0;
}

两个原子操作,注意生产者和消费者的PV操作顺序

#include <func.h>

int main(int argc,char*argv[]) {
    int ret = 0;
    int semid = semget(9010, 2, IPC_CREAT | 0666);
    
    unsigned short arr[2] = {5, 0};   
    semctl(semid, 0, SETALL, arr);
	
    //两个原子操作,empty货架,full商品
    struct sembuf empty[2], full[2];
    memset(&full, 0, sizeof(full));
    memset(&empty, 0, sizeof(empty));

    //数组下标0代表生产者对empty的操作,下标1代表消费者对empty的操作
    empty[0].sem_num = 0;  
    empty[0].sem_op = -1;
    empty[0].sem_flg = 0;
    empty[1].sem_num = 0;  
    empty[1].sem_op = 1;
    empty[1].sem_flg = 0;
    
	//数组下标0代表生产者对full的操作,下标1代表消费者对full的操作
    full[0].sem_num = 1;  
    full[0].sem_op = 1;
    full[0].sem_flg = 0;
    full[1].sem_num = 1; 
    full[1].sem_op = -1;
    full[1].sem_flg = 0;
	
    //父进程:生产者,生产商品,消耗货架
    if (fork()) {
        while(1) {
            ret = semop(semid, &empty[0], 1);
            ERROR_CHECK(ret, -1, "semop1");
            ret = semop(semid, &full[0], 1);
            ERROR_CHECK(ret, -1, "semop2");
            printf("生产者:商品的数量%d,货架的数量%d\n",
            semctl(semid,1,GETVAL), semctl(semid,0,GETVAL));
            sleep(1);
        }

    }
    //子进程:消费者,生产商品,消耗货架
    else {
        while(1) {
            ret = semop(semid, &full[1], 1);
            ERROR_CHECK(ret, -1, "semop4");
            ret = semop(semid, &empty[1], 1);
            ERROR_CHECK(ret, -1, "semop3");
            printf("消费者:商品的数量%d,货架的数量%d\n",
            semctl(semid,1,GETVAL), semctl(semid,0,GETVAL));
            sleep(3);
         }
    }
        
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值