經典同步問題三——讀者寫者問題

系列同步問題:
經典同步問題一——生產者和消費者問題
https://blog.csdn.net/weixin_36465540/article/details/105560002
經典同步問題二——哲學家進餐問題
https://blog.csdn.net/weixin_36465540/article/details/105564907
經典同步問題三——讀者寫者問題
https://blog.csdn.net/weixin_36465540/article/details/105565495

讀者寫者問題

問題描述

多個進程共享存儲區,讀取數據的稱爲讀者,寫數據的稱爲寫者。
條件:
許多讀者可以同時讀取一個文件;
每次只能有一個寫者寫文件。
如果一個寫着在寫文件,不能有讀者讀取文件。
(讀者可以一起讀,寫者之間互斥,讀與寫互斥)

讀者有優先權的解決方案

首先實現讀者可以一起讀,無需控制。

void reader() {
	while(1) {
		READUNIT();
	}
}

void writer() {
	while(1) {
		WRITEUNIT();
	}
}

接下來實現寫者互斥。

Semaphore wsem.value = 1;
void reader() {
	while(1) {
		READUNIT();
	}
}

void writer() {
	while(1) {
		wait(wsem);
		WRITEUNIT();
		signal(wsem);
	}
}

如何實現讀寫互斥?這裏我們使用一個計數器,當判斷是第一個讀者時,執行wait(wsem),再進入讀者時不執行wait(wsem),這樣讀者可以同時讀。當最後一個讀者離去時,執行signal(wsem)。這樣就實現了讀寫互斥。代碼如下。
但是這種寫法是存在缺陷的,請繼續往下看。

int readcount = 0;
Semaphore wsem.value = 1;
void reader() {
	while(1) {
		readcount++;
		if (readcount == 1)
			wait(wsem);
		READUNIT();
		readcount--;
		if (readcount == 0)
			signal(wsem);
	}
}

void writer() {
	while(1) {
		wait(wsem);
		WRITEUNIT();
		signal(wsem);
	}
}

這樣寫有一個問題,就是readcount是一個所有讀者共享的數據,對這個數據即有讀的操作,又有寫的操作,且要根據這個值判斷之後的操作,這在多進程的的時候就會存在問題。比如說這樣一種情況,一個進程在readcount++使其變爲1後,其時間片到了,另一個進程又進行了readcount++,這樣wait操作就一直沒有執行。
爲了解決這個問題,再添加一個信號量x.value,將readcount++和readcount–都放入臨界區內,避免競爭條件的產生。這樣才真正解決了讀者寫者問題。

int readcount = 0;
Semaphore wsem.value = 1;
Semaphore x.value = 1;
void reader() {
	while(1) {
		wait(x);
		readcount++;
		if (readcount == 1)
			wait(wsem);
		signal(x);
		READUNIT();
		wait(x);
		readcount--;
		if (readcount == 0)
			signal(wsem);
		signal(x);
	}
}

void writer() {
	while(1) {
		wait(wsem);
		WRITEUNIT();
		signal(wsem);
	}
}

Q:爲什麼上述方案叫讀者有優先權的解決方案?
A:因爲只要能保證一個讀者沒有運行完時,下一個讀者就到了,那麼哪怕中間有寫者想要運行,都需要等待所有的讀者運行完之後,寫者才能運行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章