天天看點

生産者消費者模型和讀者寫者模型

消費者模型

生産者-消費者問題是一個經典的程序同步問題,生産者程序在生産産品,并将這些産品提供給消費者程序去消費。為使生産者程序與消費者程序能并發執行,在兩者之間設定一個具有N個緩沖區的緩沖池,生産者程序将它所生産的産品放入一個緩沖區;消費者程序可從一個緩沖區中取走産品去消費。當緩沖區滿的時候生産者就不能放,當緩沖區空的時候消費者就不能取。

以下是我在Linux下實作的生産者消費者模型:

生産者消費者模型和讀者寫者模型
生産者消費者模型和讀者寫者模型
生産者消費者模型和讀者寫者模型

讀者寫者模型

讀者與寫者問題的特點在于讀者不使緩沖區數量改變,并且多個讀者可以同時讀取緩沖區資訊,而寫者與寫者、寫者與讀者隻能互斥通路緩沖區的相同資料。對于相同的資料項,多個讀者之間可以同時通路;對于相同的資料項,多個寫者或寫者與讀者之間不能同時通路。

兩個模型之間的差別

從兩個模型的原理中可以看出,兩個模型最大的差別在于在生産者消費者模型中,生産者與生産者是互斥關系,消費者和消費者是互斥關系,生産者和消費者之間是互斥與同步關系;而在讀者寫者模型中,讀者和讀者沒有關系,寫者和寫者是互斥關系,讀者和寫者是互斥與同步關系。

對讀者和寫者模型的深入探究

實作此模型的操作:

int count_Reader=;    //記錄正在讀的讀者數
int mutex_Count_Reader=;    //用于讀者之間互斥通路count_Reader 
int mutex_Reader_Writer=;  //用于讀者與寫者之間的互斥和寫者與寫者之間的互斥
Reader  
{  
    while(ture)  
    {  
        p( mutex_Count_Reader );  
        if(  == count_Reader )  //如果目前的讀者數為0,就要先去檢查一下是不是寫者正在寫
            p( mutex_Reader_Writer);  //如果寫者正在寫,讀者就會阻塞在此處
        ++ count_Reader;  
        v( mutex_Count_Reader);  

        進行讀操作;  

        p( mutex_Count_Reader ); 
        - - count_Reader;   
        if(  == count_Reader )  //如果讀者數已經為0,說明所有讀者都讀完了,寫者可以寫啦
            v( mutex_Reader_Writer);  
        v( mutex_Count_Reader );  
    }  
}  

Writer  
{  
    while(true)  
    {  
        p( mutex_Reader_Writer);  

        進行寫操作  

        v( mutex_Reader_Writer);  
    }  
}  
           

這其實是一個讀者優先的算法。

設想一下,如果此時有多個讀者和寫者都在等待,而此時又是讀者正在讀,讀者就一直占着mutex_Reader_Writer信号量,等待的讀者可以進去讀,但寫者就要等所有的讀者讀完後才能寫,這就會造成寫者饑餓的問題。解決方法是設定寫者優先。

寫者優先

寫者優先算法要解決的是在上面的基礎上,當讀者和寫者同時等待時,讓寫者先進去寫。

int count_Reader=;    //記錄正在讀的讀者數
int count_Writer=;    //記錄正在等待的寫者數
int mutex_Count_Reader=;    //讀者之間互斥通路count_Reader
int mutex_Count_Writer=;    //寫者之間互斥通路count_Writer
int mutex_Reader_Writer=;  //讀者與寫者之間的互斥
int mutex_write=;   //寫者與寫者之間的互斥

Reader
{
    P( mutex_Count_Writer );    //如果有寫者在等待,就阻塞讀者程序,這樣就能保證寫者優先       
    V( mutex_Count_Writer );    
    P( count_Reader );    
    if(  == count_Reader )  
        p( mutex_Reader_Writer);  //如果寫者正在寫,讀者就會阻塞在此處
    ++ count_Reader;  
    V( mutex_Count_Reader);    

    進行讀操作;         

    P( mutex_Count_Reader ); 
    - - count_Reader;   
    if(  == count_Reader )  
        v( mutex_Reader_Writer);  
    V( mutex_Count_Reader );  
}
Writer  
{  
    P( mutex_Count_Writer );              
    if(  == count_Writer )  
        p( mutex_Reader_Writer);  
    ++count_Writer;  
    V( mutex_Count_Writer);    

    寫操作;    

    P( mutex_Count_Writer );    
    - -count_Writer;    
    if(  == count_Writer )      
        V( mutex_Reader_Writer); 
    V( mutex_Count_Writer ); 
}  
           

繼續閱讀