OS不做人系列二——讀者寫者模型,絕對硬核,我保......證

前言:

     (硬核,看過絕對學到!)在上一篇博客不做人系列用了對話的方式,但是訪問量低得可憐,所以咋們還是認真的寫一篇硬核讀者寫者模型。如果你要考研的話,操作系統方面大概率會出這種類似的題目,那麼一起來學習吧。

     在我們開始學習之前,我們需要知道一些基礎的知識:

     一個數據文件或記錄可以被多個進程共享,我們把只要求讀該文件的進程稱爲“Reader進程”,其他進程則稱爲“Writer進程”。允許多個進程同時讀一個共享對象,因爲該讀操作不會使數據文件混亂。但不允許一個Writer進程和其它Reader進程或Writer進程同時訪問共享對象。因爲這種訪問必將引起混亂。所謂“讀者-寫者(Reader-Writer Problem)問題”是指保證一個Writer進程必須與其它進程互斥地訪問共享對象的同步問題。

小思考:

     那麼我們要如何實現讀者寫者模型呢?如果你看過上一篇,那麼你肯定會想到要用信號互斥量的知識點,也就是用PV原語來進行限制。當時我們說的是在臨界資源前面加P(這裏P意味着申請資源,那麼記錄減一),後面加V(這裏V意味着釋放資源,記錄加一),所以我們也就有了第一種方案。

     這裏怕大家忘記,給出PV語言(當然,也可以看上一篇哦,嘻嘻):

P原語wait(s)
--s.count;//表示申請一個資源
if(s.count<0)//表示沒有空閒資源;
{
    調用進程進入等待隊列s.queue;
    阻塞調用進程;
}
 
 
V原語signal(s)
++s.count;//表示釋放一個資源;
if(s.count<=0)//表示有進程處於阻塞狀態
{
    從等待隊列中取出一個進程P;
    進程P進入就緒隊列;
}

 

一、不成熟的方案

     那麼上面拋出了問題之後,我們首先給出最簡單的方案,直接加PV原語:

P_Reader{//這裏我們設置互斥信號量爲mutex_Blackboard
***************** 
P(mutex_Blackboard)
    ...    
    從黑板讀信息
    ...
V(mutex_Blackboard)
*****************
}


P_Writer{
***************** 
P(mutex_Blackboard)
    ...    
    向黑板寫信息
    ...
V(mutex_Blackboard)
*****************
}

優點:

     我們一看,寫者和寫者之間的確實現了互斥。

缺點:

1、來一個小例子:首先來了一個寫者,mutex_Blackboard減一,然後寫者開始操作,寫者操作完成了。又來了一個寫者,繼續操作,此時一旁的讀者,十分無奈,看!不做人了吧。

     所以,我們要改進這個方法,那麼,既然讀是可以多個的,所以我們就讓讀者優先,這些讀者高興了吧,嘻嘻。

 


二、讀者優先方案

     好的,所以我們就有了讀者優先的方案,在展示代碼之前,我們思考一下。怎麼樣纔可以實現讀者優先呢?

......動動腦子,嘻嘻嘻,越思考,越優秀!

     這個時候,你可能會說,既然讀者優先的話,那麼我們只需要讓讀者佔有這個互斥信號量就好了呀。是的,在讀者塊上加一個PV原語,進行判斷:如果是第一個讀者,那麼就搶佔mutex_Blackboard,如果是第二個,第三個讀者,那麼我們先不釋放我們的mutex_Blackboard,直到最後一個讀者要走的時候,我們再釋放資源。這個時候寫者才能拿到資源,這不就是讀者優先了嗎?讀者多開心啊。

所以,描述如下:

P_Reader{

***************** 
P(mutex_ReaderCount)//給讀者加互斥信號量mutex_ReaderCount
    ReaderCount++//進來一個加一
    if(ReaderCount==1)//如果是第一個,那麼就負責去和寫者強化mutex_Blackboard
    P(mutex_Blackboard)
V(mutex_ReaderCount)

*****************
    ...    
    從黑板讀信息
    ...
*****************

P(mutex_ReaderCount)
    ReaderCount--//如果是最後一個,把資源釋放了,給寫者(寫者真慘)
    if(ReaderCount==0)
    V(mutex_Blackboard)
V(mutex_ReaderCount)
*****************

}


P_Writer{
***************** 
P(mutex_Blackboard)
    ...    
    向黑板寫信息
    ...
V(mutex_Blackboard)
*****************
}

優點:

     的確讀者優先了,解決了上一個問題,多個讀者可以一起學習了(嘻嘻嘻)。

缺點:

     來個小例子,來了一個讀者,開始操作,來了一個寫者,掛起等待,讀者走了,又來了一個讀者........來了100個讀者,寫者一直在等待。寫者說:“你們真的不是人,不行,我們要公平競爭!!!”。

 


三、讀者寫者公平競爭方案

     所以,要公平競爭的話,我們要怎麼做呢?

......思考一下,越思考,越優秀啊

     對!聰明的你又發現了,當讀者是第一個的時候,它會搶佔資源,然後下一個讀者來,又繼續佔有,這不行啊。所以你想起了上一篇博客的記錄者沒有,那麼我們這裏在讀者和寫者搶佔mutex_Blackboard的時候加一個信號互斥量,來一個PV原語。

所以,描述如下:

P_Reader{

***************** 
P(mutex_Register)//加了一個記錄
P(mutex_ReaderCount)//給讀者加互斥信號量mutex_ReaderCount
    ReaderCount++//進來一個加一
    if(ReaderCount==1)//如果是第一個,那麼就負責去和寫者強化mutex_Blackboard
    P(mutex_Blackboard)
V(mutex_ReaderCount)
V(mutex_Register)
*****************
    ...    
    從黑板讀信息
    ...
*****************

P(mutex_ReaderCount)
    ReaderCount--//如果是最後一個,把資源釋放了,給寫者(寫者真慘)
    if(ReaderCount==0)
    V(mutex_Blackboard)
V(mutex_ReaderCount)
*****************

}


P_Writer{
***************** 
P(mutex_Register)
P(mutex_Blackboard)
    ...    
    向黑板寫信息
    ...
V(mutex_Blackboard)
v(mutex_Register)
*****************
}

優點:

     第一個讀者來了,register--,redercount--,人數加一,判斷是第一個,搶了Blackboard,釋放regiser,釋放redercount,讀操作......這個時候,來了一個寫者,regiser--,然後發現前面有人,那麼就掛起等待。這個時候,又來了一個讀者,前一個讀者完成了,就叫它的小弟上去插隊,讀者2上去,進行regiser判斷,發現前面有一個等待的,那麼不行,讀者2只好掛起等待。這個時候寫者就獲得資源,開始寫操作。一切多麼的公平啊!

     但是,寫者說:“我們不及時更新消息,你們看啥呢???不行,我們要優先"!

 


四、寫者優先方案

     好的,我們要讓寫者優先,你們想一想,要怎麼辦?

......動動腦子,嘻嘻嘻,越思考,越優秀!

     是的,是的,你又想到了,沒錯,就是給讀者加之前寫者有些的PV判斷,但是這樣還不夠呀,我們要給讀者再加一個PV,讓他們比寫者多一個資源判斷,就繼續排隊呀。哈哈,不做人了!

描述如下:

P_Reader{

***************** 
P(mutex_enhance)//再加一個,嘻嘻
P(mutex_Register)//加了一個記錄
P(mutex_ReaderCount)//給讀者加互斥信號量mutex_ReaderCount
    ReaderCount++//進來一個加一
    if(ReaderCount==1)//如果是第一個,那麼就負責去和寫者強化mutex_Blackboard
    P(mutex_Blackboard)
V(mutex_ReaderCount)
V(mutex_Register)
V(mutex_enhance)
*****************
    ...    
    從黑板讀信息
    ...
*****************

P(mutex_ReaderCount)
    ReaderCount--//如果是最後一個,把資源釋放了,給寫者(寫者真慘)
    if(ReaderCount==0)
    V(mutex_Blackboard)
V(mutex_ReaderCount)
*****************

}


P_Writer{

***************** 
P(mutex_WriterCount)
    WriterCount++
    if(WriterCount==1)
    P(mutex_Register)
V(mutex_WriterCount)  
******************

P(mutex_Blackboard)
    ...    
    向黑板寫信息
    ...
V(mutex_Blackboard)

*****************
P(mutex_WriterCount)
    WriterCount--
    if(WriterCount==0)
    V(mutex_Register)
V(mutex_WriterCount)  
*****************

}

優點:

     那麼來一遍,首先來了一個寫者,那麼進去,寫操作ing,來了一個讀者,沒有register等待。又來了一個寫者2,也是沒有Blackboard,等待。寫者1寫完了,交出了資源,這個時候讀者想要插隊,但是發現自己沒有enhance資源,只好繼續掛起。而寫者2則得到了資源,開始操作了。Oh,寫者不做人了呀。

缺點:

    寫者不做人,嘻嘻。

 

五、小小變形demo

      上面我們說了簡單的互斥,讀者優先,讀者寫者公平競爭,寫者優先,那麼看看掌握得怎麼樣了。

給出一個問題:

     【問題】:讀者有兩個組別,讀者1組合讀者2組,讀者1組和讀者2組不會同時讀黑板,但同一組中的讀者可以同時讀黑板,並會插隊。

     所以你會怎麼思考呢?小提示(不同時讀,那麼有互斥,可以同時讀,那麼可以組內優先)

所以給個參考答案吧:

P_Reader1 {

***************** 
P(mutex_Reader1Count)
    Reader1Count++
    if(Reader1Count==1)
    P(mutex_Blackboard)
V(mutex_Reader1Count)

*****************
    ...    
    從黑板讀信息
    ...
*****************

P(mutex_Reader1Count)
    ReaderCount--
    if(Reader1Count==0)
    V(mutex_Blackboard)
V(mutex_Reader1Count)
*****************

}

P_Reader2 {

***************** 
P(mutex_Reader2Count)
    Reader2Count++
    if(Reader2Count==1)
    P(mutex_Blackboard)
V(mutex_Reader2Count)

*****************
    ...    
    從黑板讀信息
    ...
*****************

P(mutex_Reader2Count)
    ReaderCount--
    if(Reader2Count==0)
    V(mutex_Blackboard)
V(mutex_Reader2Count)
*****************

}

     真厲害,那麼我們在給出一個問題吧:

 

【問題】:讀者有兩個組別,讀者1組合讀者2組,讀者1組和讀者2組不會同時讀黑板,同一組中的讀者也不可以同時讀黑板,但可以插隊。

     給出你的答案吧,下篇不做人系列我會給出參考答案哦,如果不怎麼有思路,可以試着轉換爲上面的讀寫這問題哦。

 

總結:

      好的,關於互斥的操作,簡單過了一遍吧,那麼你肯定會想,有些時候我們會要求寫者在讀者前面對吧,這個時候就涉及到了同步問題,那麼我們下一篇不做人系列見吧,如有誤,歡迎指正哦,謝謝。

     預知後事如何,請聽下回分解......

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