老和尚和小和尚打水問題


老和尚和小和尚打水問題

問題描述

某寺廟有小和尚和老和尚若干,水缸一只,由小和尚提水入缸供老和尚飲用。水缸可容水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個小和尚在水井提水\n",littleMonkCount);
        /** 小和尚在井邊提水 **/
        V(mutex1);      //小和尚打完水后釋放資源,以便給下一個小和尚繼續打水
        P(mutex2);      //小和尚回到水缸旁等待倒水,如果此時沒有其他小和尚倒水和大和尚取水,這位勤快的小和尚即可倒水
        /** 小和尚在水缸旁提水 **/
        printf("水缸已有%d桶水,第%d個小和尚在水缸旁倒水\n",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個大和尚在水缸旁提水\n",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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM