電子科技大學 820 PV 題


寫在前面:
轉載請注明本文鏈接:https://www.cnblogs.com/jxingh/p/15624566.html

PV 操作

1、生產者-消費者問題

查看源圖像
semaphore empty = n; // 表示空閑緩沖區的數量
semaphore full = 0;  // 表示滿緩沖區的數量
semaphore mutex = 1;
producer(){ // 生產者
    while(1){
        生產一個產品;
        P(empty);
        P(mutex);
        向緩沖區放入該產品;
        V(mutex);
        V(full);
    }
}
consumer(){
    while(1){
        P(full);
        P(mutex);
        從緩沖區取出一件產品;
        V(mutex);
        V(empty);
        消費一個產品;
    }
}

2、讀者-寫者問題

①允許多個讀者可以同時對文件執行讀操作;
②只允許一個寫者往文件中寫信息;
③任一寫者在完成寫操作之前不允許其他讀者或寫者工作;
④寫者執行寫操作前,應讓已有的讀者和寫者全部退出。

// 讀者優先
// 當存在讀進程時,寫操作將被延遲,並且只要有一個讀進程活躍,隨后而來的讀進程都將被允許訪問文件
// 會導致寫進程可能長時間等待,且存在寫進程“餓死”的情況
int readcount = 0;    // 表示正在進行讀的讀者數目
semaphore rmutex = 1; // 實現多個讀者對readcount的互斥訪問
semaphore mutex = 1;  // 實現對文件的互斥訪問
reader(){
    while(1){
        P(rmutex);
          if(readcount==0) P(mutex); // 第一個讀者
          readcount++;
        V(rmutex);
        讀操作;
        P(rmutex);
         readcount--;
         if(readcount==0) V(mutex); // 最后一個讀者
        V(rmutex);
    }
}
writer(){
    while(1){
        P(mutex);
        寫操作;
        V(mutex);
    }
}
// 讀寫公平
// 無論是讀者還是寫者,都按他們到達的時間先后決定優先次序
int readcount = 0;
semaphore rmutex = 1;
semaphore mutex = 1;
semaphore S = 1; // 實現先到的先進行讀或寫操作
reader(){
    while(1){
        P(S);
        P(rmutex);
          if(readcount==0) P(mutex);
          readcount++;
        V(rmutex);
        V(S);
        讀操作;
        P(rmutex);
         readcount--;
         if(readcount==0) V(mutex);
        V(rmutex);
    }
}
writer(){
    while(1){
        P(S);
        P(mutex);
        V(S);
        寫操作;
        V(mutex);
    }
}
// 寫者優先
// 先於寫者到達的讀者比寫者優先,但寫者到達后,其后續讀者必須等待寫操作完成
// 寫完成之前,有新的寫者到來,其優先權高於已在等待的讀者
int readcount = 0, writecount = 0;
semaphore rmutex = 1, wmutex = 0; // 分別實現讀者、寫者對readcount、writecount的互斥訪問
semaphore mutex = 1;
semaphore S = 1;
reader(){
    while(1){
        P(S);
        P(rmutex);
          if(readcount==0) P(mutex);
          readcount++;
        V(rmutex);
        V(S);
        讀操作;
        P(rmutex);
         readcount--;
         if(readcount==0) V(mutex);
        V(rmutex);
    }
}
writer(){
    while(1){
        P(wmutex);
          if(writecount==0) P(S); // 第一個寫者
          writecount++;
        V(wmutex);
        P(mutex);
        寫操作;
        V(mutex);
        P(wmutex);
          writecount--;
          if(writecount==0) V(S); // 最后一個寫者
        V(wmutex);
    }
}
// 寫者優先
// 寫者優先權更高。某個寫者到達后,即使前面沒有寫者,那先於他到達但還沒來得及讀的讀者必須等待他完成寫操作
int readcount = 0, writecount = 0;
semaphore rmutex = 1, wmutex = 0; // 分別實現讀者、寫者對readcount、writecount的互斥共享
semaphore mutex = 1;
semaphore S = 1;
semaphore RS = 1;
reader(){
    while(1){
        P(RS); // 避免讀者在S上排成長隊
        P(S);
        P(rmutex);
          if(readcount==0) P(mutex);
          readcount++;
        V(rmutex);
        V(S);
        V(RS);
        讀操作;
        P(rmutex);
         readcount--;
         if(readcount==0) V(mutex);
        V(rmutex);
    }
}
writer(){
    while(1){
        P(wmutex);
          if(writecount==0) P(S); // 第一個寫者
          writecount++;
        V(wmutex);
        P(mutex);
        P(mutex);
        寫操作;
        V(mutex);
        P(wmutex);
          writecount--;
          if(writecount==0) P(S); // 最后一個寫者
        V(wmutex);
    }
}

3、哲學家問題

(1)至多只允許4個哲學家同時進餐。
(2)僅當哲學家左右兩邊的筷子都可用時,才允許他進餐。

(3)規定奇數號哲學家先拿左邊的筷子,再拿右邊的筷子;而偶數號哲學家則先拿右邊的筷子,再拿左邊的筷子。

semaphore chopstick[5] = {1, 1, 1, 1, 1};
(1)
semaphore count = 4; // 設置一個count,最多有四個哲學家可以進餐
philosopher(int i){
	while(true){
		P(count); // 請求進餐,當count為0時,不能允許哲學家再進餐
		P(chopstick[i]); // 請求左手邊的筷子
		P(chopstick[(i+1)%5]); // 請求右手邊的筷子
		i號哲學家進餐;
		V(chopstick[i]); // 釋放左手邊的筷子
		V(chopstick[(i+1)%5]); // 釋放右手邊的筷子
		V(count); // 結束進餐
	}
}
(2)
semaphore mutex = 1; // 對取左側和右側筷子的操作進行保護
philosopher(int i){
	while(true){
		P(mutex); // 保護信號量
		P(chopstick[(i+1)%5]);
		P(chopstick[i]);
		V(mutex); // 釋放保護信號量
		i號哲學家進餐;
		V(chopstick[(i+1)%5]); 
		V(chopstick[i]);
	}
}
(3)
philosopher(int i){
	while(true){
		if(i%2 == 0){ //偶數哲學家,先右后左
			P(chopstick[(i+1)%5]) ;
			P(chopstick[i]) ;
			i號哲學家進餐;
			V(chopstick[(i+1)%5]) ;
			V(chopstick[i]) ;
		}
		else{ //奇數哲學家,先左后右
			P(chopstick[i]) ;
			P(chopstick[(i+1)%5]) ;
			i號哲學家進餐;
			V(chopstick[i]) ;
			V(chopstick[(i+1)%5]) ;
		}
	}
}

4、變形

(1)生產線問題

有三個進程PA、PB和PC合作解決⽂件打印問題。PA將⽂件記錄從磁盤讀⼊內存的緩沖區1,每執⾏⼀次讀⼀個記錄。PB將緩沖區1的內容復制到緩沖區2,每執⾏⼀次復制⼀個記錄。PC將緩沖區2的內容打印出來,每執⾏⼀次打印⼀個記錄。緩沖區的⼤⼩與記錄⼤⼩一樣。

semaphore empty1=1, full1=0, empty2=1, full2=0;
PA(){
    while(1){
        從磁盤讀一個記錄;
        P(empty1);
        將記錄存放在緩沖區1中;
        V(full1);
    }
}
PB(){
    P(full1);
    從緩沖區1中取出一個記錄;
    V(empty1);
    P(empty2);
    將記錄復制到緩沖區1中;
    V(full2);
}
PC(){
    P(empty1);
    從緩沖區1中取出一個記錄;
    V(full1);
    打印該記錄;
}

(2)緩沖區划分

進程A1、A2、......、An1通過m個緩沖區向進程B1、B2、......、Bn2不斷地發送消息。發送和接收工作遵循如下規則:
(1)每個發送進程一次發送一個消息,寫入一個緩沖區,緩沖區大小和消息長度相同;
(2)對每一個消息,B1、B2、.......、Bn2都需要各接收一次,讀入自己的數據區內;
(3)m個緩沖區都滿時,發送進程等待;沒有可讀的消息時,接收進程等待。

https://blog.csdn.net/silent_gods/article/details/84455122

(3)令牌問題

設有兩個生產者進程A、B和一個銷售者進程C,他們共享一個無限大的倉庫,生產者每次循環生產一個產品,然后入庫供銷售者銷售;銷售者每次循環從倉庫中取出一個產品進行銷售。如果不允許同時入庫,也不允許邊入庫邊出庫;而且要求生產A產品和B產品的件數滿足以下關系:-n<=A的件數-B的件數<=m,其中n、m是正整數,但對倉庫中A產品和B產品的件數無上述要求。

// A-B<=m  B-A<=n
// 若只生產A,而不生產B,則A產品最多可生產m次便被阻塞
// 若只生產B,而不生產A,則B產品最多可生產n次便被阻塞;
// 每生產一次A,生產產品B的機會也多一次;同理,每放入一次B,生產產品A的機會也多一次
semaphore mutex=1; // 互斥信號量
semaphore S=0;     // 當前倉庫中的產品數
semaphore SA=m;    // 當前允許A生產的產品數
semaphore SB=n;    // 當前允許B生產的產品數

LA=m LB=n
PA(){
    while(1){
        P(SA);
        生產一個產品A;
        V(SB);
        P(mutex);
        產品A入庫;
        V(mutex);
        V(S);
    }
}
PB(){
    while(1){
        P(SB);
        生產一個產品B;
        V(SA);
        P(mutex);
        產品B入庫;
        V(mutex);
        V(S);
    }
}
PC(){
    while(1){
        P(S);
        P(mutex);  
        取走一個A或B產品;
        V(mutex);
        銷售產品;
    }
}
// 思考:如果倉庫中產品數也要滿足該關系呢?

(4)理發師問題

一個理發店由一個有N張沙發的等候室和一個放有一張理發椅的理發室組成。沒有顧客要理發時,理發師便去睡覺。當一個顧客走進理發店時,如果所有的沙發都已被占用,他便離開理發店;否則,如果理發師正在為其他顧客理發,則該顧客就找一張空沙發坐下等待;如果理發師因無顧客正在睡覺,則由新到的顧客喚醒理發師為其理發。在理發完成后,顧客必須付費,直到理發師收費后才能離開理發店。

int count=0; // 沙發上人數
semaphore mutex; // 實現不同顧客對count的互斥共享
semaphore empty=1,full=0; // 理發椅是否空閑
semaphore payment=0,receipt=0; // 等待付費、收費
guest(){
    P(mutex);
    if(count>=N){
        V(mutex);
        離開理發店;
    }else{
          count++;
        V(mutex);
        在沙發等待;
        P(empty);  // 等待理發椅變空
        離開沙發,坐到理發椅上;
        P(mutex);
          count--;
        V(mutex);
        V(full);  // 喚醒理發師
        理發;
        付費;
        V(payment);  // 通知理發師收費
        P(receipt);  // 等待理發師收費
        V(empty);    // 離開理發椅
        離開理發店;
    }
}
Barber(){
    while(1){
        P(full);    // 等待理發椅來人
        給顧客理發;
        P(payment); // 等待顧客付費
        收費;
        V(receipt); // 通知顧客已收費

    }
}

(5)獨木橋問題

同一方向的行人可連續過橋,當某一方向有人過橋時,另一方向的行人必須等待;當某一方向無人過橋時,另一方向的行人可以過橋。

int countA=0, countB=0;        // 分別表示A、B兩個方向過橋的人數
semaphore mutex=1;             // 不同方向行人互斥過橋
semaphore mutexA=1, mutexB=1;  // 分別實現對countA、countB的互斥訪問
PA(){
    while(1){
        P(mutexA);
          if(countA==0) P(mutex); // 第一個過橋
          countA++;
        V(mutexA);
        過橋;
        P(mutexA);
          countA--;
          if(countA==0) V(mutex); // 最后一個過橋
        V(mutexA);
    }
}


免責聲明!

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



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