問(wèn)題描述
有讀者和寫(xiě)者兩組并發(fā)進(jìn)程,共享一個(gè)文件根资,當(dāng)兩個(gè)或以上的讀進(jìn)程同時(shí)訪問(wèn)共享數(shù)據(jù)時(shí)不會(huì)產(chǎn)生副作用架专,但若某個(gè)寫(xiě)進(jìn)程和其他進(jìn)程(讀進(jìn)程或?qū)戇M(jìn)程)同時(shí)訪問(wèn)共享數(shù)據(jù)時(shí)則可能導(dǎo)致數(shù)據(jù)不一致的錯(cuò)誤。因此要求:①允許多個(gè)讀者可以同時(shí)對(duì)文件執(zhí)行讀操作玄帕;②只允許一個(gè)寫(xiě)者往文件中寫(xiě)信息部脚;③任一寫(xiě)者在完成寫(xiě)操作之前不允許其他讀者或?qū)懻吖ぷ鳎虎軐?xiě)者執(zhí)行寫(xiě)操作前裤纹,應(yīng)讓已有的讀者和寫(xiě)者全部退出委刘。
問(wèn)題分析
- 關(guān)系分析。由題目分析讀者和寫(xiě)者是互斥的鹰椒,寫(xiě)者和寫(xiě)者也是互斥的锡移,而讀者和讀者不存在互斥問(wèn)題。
- 整理思路漆际。兩個(gè)進(jìn)程淆珊,即讀者和寫(xiě)者。寫(xiě)者是比較簡(jiǎn)單的奸汇,它和任何進(jìn)程互斥施符,用互斥信號(hào)量的P操作、V操作即可解決茫蛹。讀者的問(wèn)題比較復(fù)雜操刀,它必須實(shí)現(xiàn)與寫(xiě)者互斥的同時(shí)還要實(shí)現(xiàn)與其他讀者的同步,因此婴洼,僅僅簡(jiǎn)單的一對(duì)P操作骨坑、V操作是無(wú)法解決的。那么柬采,在這里用到了一個(gè)計(jì)數(shù)器欢唾,用它來(lái)判斷當(dāng)前是否有讀者讀文件。當(dāng)有讀者的時(shí)候?qū)懻呤菬o(wú)法寫(xiě)文件的粉捻,此時(shí)讀者會(huì)一直占用文件礁遣,當(dāng)沒(méi)有讀者的時(shí)候?qū)懻卟趴梢詫?xiě)文件。同時(shí)這里不同讀者對(duì)計(jì)數(shù)器的訪問(wèn)也應(yīng)該是互斥的肩刃。
- 信號(hào)量設(shè)置祟霍。首先設(shè)置信號(hào)量count為計(jì)數(shù)器,用來(lái)記錄當(dāng)前讀者數(shù)量盈包,初值為0; 設(shè)置mutex為互斥信號(hào)量沸呐,用于保護(hù)更新count變量時(shí)的互斥;設(shè)置互斥信號(hào)量rw用于保證讀者和寫(xiě)者的互斥訪問(wèn)呢燥。
代碼如下:
int count=0; //用于記錄當(dāng)前的讀者數(shù)量
semaphore mutex=1; //用于保護(hù)更新count變量時(shí)的互斥
semaphore rw=1; //用于保證讀者和寫(xiě)者互斥地訪問(wèn)文件
writer () { //寫(xiě)者進(jìn)程
while (1){
P(rw); // 互斥訪問(wèn)共享文件
Writing; //寫(xiě)入
V(rw) ; //釋放共享文件
}
}
reader () { // 讀者進(jìn)程
while(1){
P (mutex) ; //互斥訪問(wèn)count變量
if (count==0) //當(dāng)?shù)谝粋€(gè)讀進(jìn)程讀共享文件時(shí)
P(rw); //阻止寫(xiě)進(jìn)程寫(xiě)
count++; //讀者計(jì)數(shù)器加1
V (mutex) ; //釋放互斥變量count
reading; //讀取
P (mutex) ; //互斥訪問(wèn)count變量
count--; //讀者計(jì)數(shù)器減1
if (count==0) //當(dāng)最后一個(gè)讀進(jìn)程讀完共享文件
V(rw) ; //允許寫(xiě)進(jìn)程寫(xiě)
V (mutex) ; //釋放互斥變量 count
}
}
在上面的算法中崭添,讀進(jìn)程是優(yōu)先的,也就是說(shuō)叛氨,當(dāng)存在讀進(jìn)程時(shí)呼渣,寫(xiě)操作將被延遲棘伴,并且只要有一個(gè)讀進(jìn)程活躍,隨后而來(lái)的讀進(jìn)程都將被允許訪問(wèn)文件屁置。這樣的方式下焊夸,會(huì)導(dǎo)致寫(xiě)進(jìn)程可能長(zhǎng)時(shí)間等待,且存在寫(xiě)進(jìn)程“餓死”的情況缰犁。
如果希望寫(xiě)進(jìn)程優(yōu)先淳地,即當(dāng)有讀進(jìn)程正在讀共享文件時(shí),有寫(xiě)進(jìn)程請(qǐng)求訪問(wèn)帅容,這時(shí)應(yīng)禁止后續(xù)讀進(jìn)程的請(qǐng)求,等待到已在共享文件的讀進(jìn)程執(zhí)行完畢則立即讓寫(xiě)進(jìn)程執(zhí)行伍伤,只有在無(wú)寫(xiě)進(jìn)程執(zhí)行的情況下才允許讀進(jìn)程再次運(yùn)行并徘。為此,增加一個(gè)信號(hào)量并且在上面的程序中 writer()和reader()函數(shù)中各增加一對(duì)PV操作扰魂,就可以得到寫(xiě)進(jìn)程優(yōu)先的解決程序麦乞。
int count = 0; //用于記錄當(dāng)前的讀者數(shù)量
semaphore mutex = 1; //用于保護(hù)更新count變量時(shí)的互斥
semaphore rw=1; //用于保證讀者和寫(xiě)者互斥地訪問(wèn)文件
semaphore w=1; //用于實(shí)現(xiàn)“寫(xiě)優(yōu)先”
writer(){
while(1){
P(w); //在無(wú)寫(xiě)進(jìn)程請(qǐng)求時(shí)進(jìn)入
P(rw); //互斥訪問(wèn)共享文件
writing; //寫(xiě)入
V(rw); // 釋放共享文件
V(w) ; //恢復(fù)對(duì)共享支件的訪問(wèn)
}
}
reader () { //讀者進(jìn)程
while (1){
P (w) ; // 在無(wú)寫(xiě)進(jìn)程請(qǐng)求時(shí)進(jìn)入
P (mutex); // 互斥訪問(wèn)count變量
if (count==0) //當(dāng)?shù)谝粋€(gè)讀進(jìn)程讀共享文件時(shí)
P(rw); //阻止寫(xiě)進(jìn)程寫(xiě)
count++; //讀者計(jì)數(shù)器加1
V (mutex) ; //釋放互斥變量count
V(w); //恢復(fù)對(duì)共享文件的訪問(wèn)
reading; //讀取
P (mutex) ; //互斥訪問(wèn)count變量
count--; //讀者計(jì)數(shù)器減1
if (count==0) //當(dāng)最后一個(gè)讀進(jìn)程讀完共享文件
V(rw); //允許寫(xiě)進(jìn)程寫(xiě)
V (mutex); //釋放互斥變量count
}
}