c语言管程例子,管程 - it610.com
一、信號(hào)量的缺點(diǎn)
信號(hào)量的使用一定要小心,如下圖中解決生產(chǎn)者-消費(fèi)者問題的程序:
如果在producer的執(zhí)行函數(shù)中,將empty與mutex的down操作互換,如果此時(shí)mutex為0,將首先對(duì)mutex進(jìn)行down操作,進(jìn)程陷入阻塞,而同時(shí),當(dāng)consumer的執(zhí)行函數(shù)執(zhí)行到down(&mutex)的時(shí)候,由于mutex為0,因此,consumer線程也將進(jìn)入阻塞,兩個(gè)進(jìn)程都將永遠(yuǎn)進(jìn)入阻塞狀態(tài),這被稱為“死鎖”
這說明使用信號(hào)量時(shí)一定要非常小心,一處很小的錯(cuò)誤將有可能導(dǎo)致很大的麻煩,因?yàn)楦偁帡l件、死鎖以及其他一些問題都是不可預(yù)測(cè)和不可再現(xiàn)的行為
為了更易于編寫正確的程序,一種高級(jí)同步原語?--?管程(monitor)誕生了
二、管程
一個(gè)管程是一個(gè)由過程、變量及數(shù)據(jù)結(jié)構(gòu)等組成的一個(gè)集合,它們組成一個(gè)特殊的模塊或軟件包。
管程內(nèi)部的共享變量
管程內(nèi)部的條件變量
管程內(nèi)部并行執(zhí)行的進(jìn)程
對(duì)局部于管程內(nèi)部的共享數(shù)據(jù)設(shè)置初始值的語句
進(jìn)程可以在任何需要的時(shí)候調(diào)用管程中的過程,但是他們不能在管程之外聲明的過程中直接訪問管程內(nèi)的數(shù)據(jù)結(jié)構(gòu)
但是,需要注意的是管程是語言概念,而C語言并不支持它
任意時(shí)刻,管程中只能有一個(gè)活躍的進(jìn)程,這一特性是的管程能夠有效地完成互斥,由編譯器選擇采取與其他過程調(diào)用不同的方法來處理對(duì)管程的調(diào)用
典型的處理方法是,當(dāng)一個(gè)進(jìn)程調(diào)用管程過程時(shí),該過程中的前幾條指令將檢查在管程中是否有其他的活躍進(jìn)程,如果有,調(diào)用進(jìn)程將被掛起,知道另一個(gè)進(jìn)程離開管程將其喚醒,如果沒有,則該調(diào)用進(jìn)程可以進(jìn)入
進(jìn)入管程時(shí)的互斥由編譯器負(fù)責(zé),但通常的做法是用一個(gè)互斥量或二元信號(hào)量,因?yàn)槭怯芯幾g器而非程序員來安排互斥,所以出錯(cuò)的可能性要小得多
在任何一個(gè)時(shí)刻,寫管程的人無需關(guān)心編譯器是如何實(shí)現(xiàn)互斥的,他只需要知道將所有的臨界區(qū)轉(zhuǎn)換成管程過程即可,絕不會(huì)有兩個(gè)進(jìn)程同時(shí)執(zhí)行臨界區(qū)中的代碼。
三、管程中的條件變量
管程提供了一種實(shí)現(xiàn)互斥的漸變途徑,但是我們還需要一種辦法使得進(jìn)程在無法繼續(xù)運(yùn)行時(shí)被阻塞,解決這個(gè)問題的方法就是引入條件變量,以及相關(guān)的兩個(gè)操作:wait和signal,當(dāng)一個(gè)管程過程發(fā)現(xiàn)他無法繼續(xù)運(yùn)行時(shí)(如生產(chǎn)者發(fā)現(xiàn)緩沖區(qū)已滿),他會(huì)在某個(gè)條件變量上(如full)上執(zhí)行wait操作,該操作導(dǎo)致調(diào)用進(jìn)程自身阻塞,并將另一個(gè)等在管程外的進(jìn)程調(diào)入管程,同時(shí),一個(gè)進(jìn)程也可以通過對(duì)伙伴正在等待的一個(gè)條件變量執(zhí)行signal操作完成喚醒正在睡眠的伙伴進(jìn)程,但是這個(gè)時(shí)候就有可能會(huì)出現(xiàn)兩個(gè)活躍進(jìn)程同時(shí)處在管程中的情況,這個(gè)情況有兩種方案可以解決:
運(yùn)行新喚醒的進(jìn)程,掛起之前的進(jìn)程
執(zhí)行signal的進(jìn)程立即退出管程,即規(guī)定signal只能作為管程過程的最后一條語句
讓發(fā)信者繼續(xù)運(yùn)行直到發(fā)信者退出管程后才讓被喚醒的進(jìn)程運(yùn)行
很明顯,第一種方案更加簡單,所以一般我們采取這一方案
注意,條件變量與信號(hào)量不同,他并不是計(jì)數(shù)器,如果向一個(gè)條件變量發(fā)送信號(hào),而這個(gè)條件變量上此時(shí)并沒有等待進(jìn)程,則這個(gè)信號(hào)就會(huì)丟失,也就是說wait必須在signal之前執(zhí)行
wait、signal與sleep、wakeup最大的區(qū)別是他們不存在嚴(yán)重的競爭條件,因?yàn)榭赡艽嬖谝环N情況,即當(dāng)一個(gè)進(jìn)程正要去sleep而實(shí)際還沒有sleep的時(shí)候,另一個(gè)進(jìn)程企圖喚醒他,從而造成了wakeup信號(hào)的丟失,而管程中不會(huì)存在這樣的問題,因?yàn)樵诰彌_區(qū)滿,生產(chǎn)者wait前,消費(fèi)者進(jìn)程根本不可能進(jìn)入管程
四、代碼示例
如圖所示,是用管程實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者問題揭發(fā)框架的一個(gè)類似于pascal的偽代碼
java支持用戶級(jí)進(jìn)程,只要將關(guān)鍵詞synchronized加入到方法聲明中,java就保證這個(gè)方法一旦被某個(gè)進(jìn)程執(zhí)行,就不允許其他進(jìn)程執(zhí)行它,因此我們可以通過這一特性實(shí)現(xiàn)管程的編程
這個(gè)例子其實(shí)并不難懂,由于有synchronized關(guān)鍵字,所以無論是producer要進(jìn)行的insert方法還是consumer要進(jìn)行的remove方法都只能讓一個(gè)進(jìn)程進(jìn)入,因此他們不需要再擔(dān)心競爭條件
java中并沒有條件變量,反之,java提供了兩個(gè)過程:wait和notify,與sleep和wakeup等價(jià),但他們并不受競爭條件約束,而是通過異常機(jī)制實(shí)現(xiàn)對(duì)中斷情況的處理
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的c语言管程例子,管程 - it610.com的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《无名》领跑!兔年大年初一预售票房破亿
- 下一篇: c语言二维数组赋值前面是行还是列,动态二