1. 程式人生 > >讀者-寫者問題 寫者優先與公平競爭

讀者-寫者問題 寫者優先與公平競爭

設有一檔案F,多個併發讀程序和寫程序都要訪問,要求:

(1)讀寫互斥

(2)寫寫互斥

(3)允許多個讀程序同時訪問

採用記錄型訊號量機制解決

較常見的寫法:

semaphore fmutex=1, rdcntmutex=1;

//fmutex --> access to file; rdcntmutex --> access to readcount

int readcount = 0;

void reader(){

    while(1){

        wait(rdcntmutex);

        if(0 == readcount)wait(fmutex);

        readcount = readcount + 1;

        signal(rdcntmutex);

        //Do read operation ...

        wait(rdcntmutex);

        readcount = readcount - 1;

        if(0 == readcount)signal(fmutex);

        signal(rdcntmutex);

    }

}

void writer(){

    while(1){

        wait(fmutex);

        //Do write operation ...

        signal(fmutex);

    }

}

讀程序只要看到有其他讀程序正在訪問檔案,就可以繼續作讀訪問;寫程序必須等待所有讀程序都不訪問時才能寫檔案,即使寫程序可能比一些讀程序更早提出申請。所以以上解法實際是讀者優先 的解法。如果在讀訪問非常頻繁的場合,有可能造成寫程序一直無法訪問檔案的局面....

為了解決以上問題,需要提高寫程序的優先順序。這裡另增加一個排隊訊號量:queue。讀寫程序訪問檔案前都要在此訊號量上排隊,通過區別對待讀寫程序便可達到提高寫程序優先順序的目的。另外再增加一個 writecount 以記錄提出寫訪問申請和正在寫的程序總數:

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 訊號量,之後在真正做讀操作前即讓出(使得寫程序可以隨時申請到 queue)。而只有第一個寫程序需要申請 queue,之後就一直佔著不放了,直到所有寫程序都完成後才讓出。等於只要有寫程序提出申請就禁止讀程序排隊,變相提高了寫程序的優先順序。

通過類似思想即可實現讀寫程序的公平競爭:

semaphore fmutex=1, rdcntmutex=1, queue=1;

//fmutex --> access to file; rdcntmutex --> access to readcount

int readcount = 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(queue);

        wait(fmutex);

        signal(queue);

        //Do write operation ...

        signal(fmutex);

    }

}

讀程序沒變,寫程序變成在每次寫操作前都要等待 queue 訊號量。

課本上一般只會寫第一種解法吧。看了後兩種方法即可發現,在第一個解法中,fmutex 訊號量實際是雙重身份,首先實現對檔案的互斥訪問,其次起到了和後面排隊訊號量 queue 相同的作用,只不過在那種排序下只能是讀者優先。如果直接看過後兩種解法,應該會有更清楚的理解吧。