讀寫互斥,寫寫互斥,讀讀可併發併發
信號量:w=1(可寫),mutex=1(可讀)
共享變量:rcount=0(讀者數量)spa
//僞代碼 int rcount=0 semaphore w=1,mutex=1 reader(){ P(mutex); rcount++; if(rcount==1) P(w);//堵塞寫者,保證全部讀者讀完 V(mutex); //以上保證全部讀者均可同時讀 //Read() P(mutex); rcount--; if(rcount==0) V(w); V(mutex); } writer(){ P(w); //write() V(w); }
存在問題,讀者過多,餓死寫者(rcount減小同時也在增長)。.net
增長wcount標記寫者存在,若是同時存在讀寫者,讀者在執行時經過P(w)阻塞寫者,而寫者wcount標記存在,經過P(r)防止讀者繼續加入。code
P(x)與V(x)用以保護原子操做blog
int wcount=0,rcount=0; semaphore w=1,r=1,x=1; reader(){ P(r); P(x); rcount++; if(rcount==1) P(w); V(x); V(r); //Read() P(x); rcount--; if(rcount==0) V(w); V(x); } writer(){ P(x); wcount++; if(wcount==1) P(r); V(x); P(w); //Write() V(w); P(x); wcount--; if(wcount==0) V(r); V(x); }
進程同步的經典問題1——讀者寫者問題(寫者優先與公平競爭)
能夠參考,這是代碼進程
semaphore fmutex=1, rdcntmutex=1, wtcntmutex=1, queue=1; //fmutex --> access to file; rdcntmutex --> access to readcount //wtcntmutex --> access to writecount int readcount = 0, writecount = 0; void reader(){ while(1){ wait(queue); wait(rdcntmutex); if(0 == readcount)wait(fmutex); readcount = readcount + 1; signal(rdcntmutex); signal(queue); //Do read operation ... wait(rdcntmutex); readcount = readcount - 1; if(0 == readcount)signal(fmutex); signal(rdcntmutex); } } void writer(){ while(1){ wait(wtcntmutex); if(0 == writecount)wait(queue); writecount = writecount + 1; signal(wtcntmutex); wait(fmutex); //Do write operation ... signal(fmutex); wait(wtcntmutex); writecount = writecount - 1; if(0 == writecount)signal(queue); signal(wtcntmutex); } }
增長一個排隊信號量:queue。讀寫進程訪問文件前都要在此信號量上排隊,經過區別對待讀寫進程即可達到提升寫進程優先級的目的。另外再增長一個 writecount 以記錄提出寫訪問申請和正在寫的進程總數.
每一個讀進程最開始都要申請一下 queue 信號量,以後在真正作讀操做前即讓出(使得寫進程能夠隨時申請到 queue)。而只有第一個寫進程須要申請 queue,以後就一直佔着不放了,直到全部寫進程都完成後才讓出。等於只要有寫進程提出申請就禁止讀進程排隊,變相提升了寫進程的優先級。 get