zoukankan      html  css  js  c++  java
  • 老和尚和小和尚打水问题

    老和尚和小和尚打水问题

    问题描述

    某寺庙有小和尚和老和尚若干,水缸一只,由小和尚提水入缸供老和尚饮用。水缸可容水10桶,水取自同一口水井中。水井径窄,每次仅能容纳一只水桶取水,水桶共三只。每次放入、取出的水量仅为一桶,试用PV操作写出小和尚打水、放入水缸、老和尚取水喝的过程。

    问题分析

    明确行为对象:小和尚、老和尚

    明确临界区:

    水井:小和尚之间互斥

    水缸:小和尚、大和尚之间互斥

    水桶:小和尚、大和尚之间互斥

    明确信号量:

    1.n个小和尚到水井提水时互斥,用mutex1控制

    2.小和尚将水放入水缸和老和尚取水互斥,用mutex2控制

    3.临界区是空闲的水桶数量,老和尚和小和尚都要用,用amount控制

    4.使用full来表示水缸里有几桶水,用empty来表示水缸里还能放几桶水

    算法描述

    semaphore mutex1=1,mutex2=1;
    semaphore amount=5,empty=30,full=0;
    
    void LittleMonk i(i=1,2,3,,,n) ()
    {
    	while(TRUE)
    	{
    		P(empty);
    		p(amount);
    		P(mutex1);
    		小和尚从井里打水;
    		V(mutex1);
    		P(mutex2);
    		往缸里面倒水;
    		V(mutex2);
    		V(amount);
    		V(full); 
    	}
    }
    
    void BigMonk i(i=1,2,3,,,n) ()
    {
    	while(TRUE)
    	{
    		P(full);
    		P(amount);
    		P(mutex2);
    		从缸里面取水使用;
    		V(mutex2);
    		V(amount);
    		V(empty); 
    	}
    }
    
    void mian()
    {
    	cobegin
    	young monk i(i=1,2,3,,,n) ();
    	old monk i(i=1,2,3,,,n) ();
    	coend
    }
    

    代码实现

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    
    #define P sem_wait
    #define V sem_post 
    #define mutex1 &muteX1
    #define mutex2 &muteX2
    #define amount &Amount
    #define empty &Empty
    #define full &Full
    
    
    
    #define N 10
    
    sem_t muteX1,muteX2;
    sem_t Amount,Empty,Full;
    
    
    int littleMonkCount= 0;
    int BigMonkCount = 0; 
    int fullcount = 0;
    int sum=50;
    
    
    void* LittleMonk(void *p)
    {
        while(sum)
        {   
            sum--;
            P(empty);       //小和尚打水先要看看水缸里是否满了,没满才能够打水,可以打水的容量-1,毕竟这位小和尚去打了
            littleMonkCount++;
            P(amount);      //想打水可还不行,还要看看有没有打水桶可以用,抢到了水桶就可以继续打水,可用水桶-1
            P(mutex1);      //小和尚拿着桶到了水井,如果没有其他的小和尚在打水,这位勤快的小和尚才能打水
            /** 小和尚在井边提水 **/
            printf("第%d个小和尚在水井提水
    ",littleMonkCount);
            /** 小和尚在井边提水 **/
            V(mutex1);      //小和尚打完水后释放资源,以便给下一个小和尚继续打水
            P(mutex2);      //小和尚回到水缸旁等待倒水,如果此时没有其他小和尚倒水和大和尚取水,这位勤快的小和尚即可倒水
            /** 小和尚在水缸旁提水 **/
            printf("水缸已有%d桶水,第%d个小和尚在水缸旁倒水
    ",fullcount,littleMonkCount);
            fullcount++;
            /** 小和尚在水缸旁提水 **/
            V(mutex2);      //小和尚倒完水后走开,以便给下一个和尚打水或提水
            V(amount);      //这位勤奋的小和尚完成了他的任务,放下了他的水桶,可用水桶+1
            littleMonkCount--;
            V(full);        //多亏了这位勤快的小和尚,水缸里又多了一桶水
        }
    }
    
    
    void* BigMonk(void *p)
    {
        int myFull;
        while(sum)
        {
            sum--;
            P(full);        //大和尚瞧了瞧水缸里,如果有水,就去找水桶准备打水,没有则在旁边等候,这时候相当于老和尚已经预定了这桶水
            BigMonkCount++;
            P(amount);      //大和尚看到有水了赶紧去抢水桶,抢不到又得等,抢到了接着急冲冲跑向水缸
            P(mutex2);      //跑到了水缸旁,看到有人有和尚在使用水缸则等待,没有和尚在使用则开始打水
            /** 大和尚在水缸旁提水 **/
            printf("    水缸已有%d桶水,第%d个大和尚在水缸旁提水
    ",fullcount,BigMonkCount);
            fullcount--;
            /** 大和尚在水缸旁提水 **/
            V(mutex2);      //大和尚提完水后离去,以便给下一个和尚使用水缸
            V(amount);      //不要忘了放水桶给下一个和尚用
            BigMonkCount--;
            V(empty);       //可以打水的数量+1
        }
    }
    
    
    int main()
    {
        int i,j;
        /** 初始化资源个数 **/
        sem_init(mutex1, 0, 1);     //互斥锁默认为1
        sem_init(mutex2,0,1);       //互斥锁默认为1
        sem_init(amount,0,3);       //开始时有3个水桶供使用
        sem_init(full,0,0);         //开始时水缸里没有水,设置为0
        sem_init(empty,0,10);       //开始时水缸里最多能装10桶水,设置为10
    
        /** 创建多个大和尚进程 **/
        for(i=1;i<=4;i++){
            pthread_t i;
            pthread_create(&i, NULL,BigMonk, NULL);
        }
    
        /** 创建多个小和尚进程 **/
        for(j=1;j<=10;j++){
            pthread_t j;
            pthread_create(&j, NULL,LittleMonk, NULL);
        }
        
        /**观察结果后关闭进程**/
        getchar();
        pthread_exit(0);
        return 0;
    }
    
    

    运行结果

    1588156473600

  • 相关阅读:
    页面转表格并且下载
    关于表格导入
    C/C++作用域运算符::
    设计模式之观察者模式_C++
    C# 传不定参数
    C语言中的位域的使用
    C++/python求哈希值(SHA256)
    C++中纯虚函数
    类模板/函数模板实现父类指针指向子类对象(虚函数实现多态)
    Windows Socket 接口简介
  • 原文地址:https://www.cnblogs.com/lightice/p/12852712.html
Copyright © 2011-2022 走看看