摘要:那并發(fā)里面的理論和模型是什么呢那便要從操作系統(tǒng)中解決并發(fā)問題的一種模型管程講起了。當(dāng)一個(gè)進(jìn)程使用完管程后,它必須釋放管程并喚醒等待管程的某一個(gè)進(jìn)程??偨Y(jié)在并發(fā)編程領(lǐng)域,有兩大核心問題互斥和同步,而這兩個(gè)問題,管程模型都可以解決。
為什么需要了解管程
Java并發(fā)編程是Java中高級(jí)程序員必備的一項(xiàng)技能,但是真正學(xué)明白并發(fā)編程也并非易事。正如Java并發(fā)編程實(shí)踐中的一句話“編寫正確的程序并不容易,而編寫正確的并發(fā)程序就更難了”,Java里并發(fā)的知識(shí)很瑣碎,看懂難,會(huì)用更難。然后,我們常常一頭扎進(jìn)了Java并發(fā)編程技術(shù)的細(xì)節(jié),卻發(fā)現(xiàn)剪不斷理還亂,終不得要領(lǐng)。這是因?yàn)槲覀兒雎粤思夹g(shù)背后的理論和模型,而理論和模型往往比具體的技術(shù)更為重要。那Java并發(fā)里面的理論和模型是什么呢?那便要從操作系統(tǒng)中解決并發(fā)問題的一種模型管程講起了。
什么是管程管程是將共享變量及對(duì)共享變量的操作封裝起來的管理程序。操作系統(tǒng)中的描述為:代表共享資源的數(shù)據(jù)結(jié)構(gòu),以及由對(duì)該共享數(shù)據(jù)結(jié)構(gòu)實(shí)施操作的一組過程所組成的資源管理程序,共同構(gòu)成了一個(gè)操作系統(tǒng)的資源管理模塊,我們稱之為管程。管程的示意圖如下:
管程如何解決互斥管程內(nèi)部的數(shù)據(jù)結(jié)構(gòu),僅能被管程內(nèi)部的過程所訪問,任何管程外的過程都不能訪問它;反之,局部于管程內(nèi)部的過程也僅能訪問管程內(nèi)的數(shù)據(jù)結(jié)構(gòu)。由此可見,管程相當(dāng)于圍墻,它把共享變量和對(duì)它進(jìn)行操作的若干過程圍了起來,所有進(jìn)程要訪問臨界資源時(shí),都必須經(jīng)過管程(相當(dāng)于通過圍墻的門)才能進(jìn)入,而管程每次只準(zhǔn)許一個(gè)進(jìn)程進(jìn)入管程,從而實(shí)現(xiàn)了進(jìn)程互斥。即當(dāng)一個(gè)進(jìn)程使用管程時(shí),另一個(gè)進(jìn)程必須等待。當(dāng)一個(gè)進(jìn)程使用完管程后,它必須釋放管程并喚醒等待管程的某一個(gè)進(jìn)程。
管程如何解決同步管程里引入了條件變量的概念來解決同步問題,而且每個(gè)條件變量都對(duì)應(yīng)有一個(gè)等待隊(duì)列,條件變量對(duì)應(yīng)的3個(gè)方法為wait()、notify()、notifyAll()。示意圖如下:
線程先在入口等待隊(duì)列排隊(duì)進(jìn)入管程,這確保了互斥訪問管程。當(dāng)線程進(jìn)入管程后,如果發(fā)現(xiàn)條件變量A不滿足,則需要調(diào)用A.wait()使線程進(jìn)入A的條件變量等待隊(duì)列,此時(shí)其他在入口等待隊(duì)列的線程可以繼續(xù)進(jìn)入管程。如果當(dāng)條件變量A滿足條件時(shí),則調(diào)用A.notify()或則A.notifyAll()(notify是通知等待隊(duì)列中的一個(gè)線程,notifyAll是通知所有線程)方法通知在A條件變量等待隊(duì)列中的線程,然后該線程會(huì)重新進(jìn)入入口等待隊(duì)列中排隊(duì)進(jìn)入管程。如此便實(shí)現(xiàn)了線程間的同步。
這與就醫(yī)流程相似,患者掛了號(hào)后,然后就到就診門口分診,等待叫號(hào)(類似入口等待隊(duì)列);當(dāng)叫到自己的號(hào)時(shí),患者就可以找大夫就診了,就診過程中,大夫開了個(gè)驗(yàn)血的單子(類似條件等待隊(duì)列)那現(xiàn)在就需求去驗(yàn)血的隊(duì)伍里排隊(duì),同時(shí)醫(yī)生可以給其他患者診治;等患者做完檢查,拿到檢查報(bào)告后需要重新排隊(duì)分診(線程重新進(jìn)入入口等待隊(duì)列)。
在并發(fā)編程領(lǐng)域,有兩大核心問題:互斥和同步,而這兩個(gè)問題,管程模型都可以解決。管程模型中利用入口等待隊(duì)列,保證同一時(shí)間只有一個(gè)線程進(jìn)入管程,實(shí)現(xiàn)線程間的互斥;利用條件變量及條件變量等待隊(duì)列實(shí)現(xiàn)線程間的同步。Java中的synchronized以及l(fā)ock都是管程模型的一種實(shí)現(xiàn),了解了管程模型后,對(duì)后續(xù)深入學(xué)習(xí)Java并發(fā)大有好處。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76063.html
摘要:語言在之前,提供的唯一的并發(fā)原語就是管程,而且之后提供的并發(fā)包,也是以管程技術(shù)為基礎(chǔ)的。但是管程更容易使用,所以選擇了管程。線程進(jìn)入條件變量的等待隊(duì)列后,是允許其他線程進(jìn)入管程的。并發(fā)編程里兩大核心問題互斥和同步,都可以由管程來幫你解決。 并發(fā)編程這個(gè)技術(shù)領(lǐng)域已經(jīng)發(fā)展了半個(gè)世紀(jì)了。有沒有一種核心技術(shù)可以很方便地解決我們的并發(fā)問題呢?這個(gè)問題, 我會(huì)選擇 Monitor(管程)技術(shù)。Ja...
摘要:請(qǐng)參看前一篇文章并發(fā)學(xué)習(xí)筆記一原子性可見性有序性問題六等待通知機(jī)制什么是等待通知機(jī)制當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài)如果線程滿足要求的某個(gè)條件后,則通知等待的線程重新執(zhí)行。經(jīng)極客時(shí)間并發(fā)編程實(shí)戰(zhàn)專欄內(nèi)容學(xué)習(xí)整理 請(qǐng)參看前一篇文章:Java 并發(fā)學(xué)習(xí)筆記(一)——原子性、可見性、有序性問題 六、等待—通知機(jī)制 什么是等待通知—機(jī)制?當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài);如果線程滿足要...
摘要:當(dāng)前線程使用將對(duì)象頭的替換為鎖記錄指針,如果成功,當(dāng)前線程獲得鎖如果失敗,表示其他線程競(jìng)爭(zhēng)鎖,當(dāng)前線程便嘗試使用自旋來獲取鎖。重量級(jí)鎖是悲觀鎖的一種,自旋鎖輕量級(jí)鎖與偏向鎖屬于樂觀鎖。 操作系統(tǒng)在面對(duì)線程間同步的時(shí)候,會(huì)支持例如semaphore信號(hào)量和mutex互斥量等同步原語,而monitor是在編程語言中被實(shí)現(xiàn)的,下面介紹一下java中monitor(監(jiān)視器/管程:管理共享變量以...
摘要:誕生之處就支持多線程,所以自然有解決這些問題的辦法,而且在編程語言領(lǐng)域處于領(lǐng)先地位。,線程規(guī)則這條是關(guān)于線程啟動(dòng)的。在語言里面,的語義本質(zhì)上是一種可見性,意味著事件對(duì)事件來說是可見的,無論事件和事件是否發(fā)生在同一個(gè)線程里。 之前我們說了:1,可見性2,原子性3,有序性3個(gè)并發(fā)BUG的之源,這三個(gè)也是編程領(lǐng)域的共性問題。Java誕生之處就支持多線程,所以自然有解決這些問題的辦法,而且在編...
摘要:在這個(gè)等待通知機(jī)制中,我們需要考慮以下四個(gè)要素。何時(shí)等待線程要求的條件不滿足就等待。是會(huì)隨機(jī)地通知等待隊(duì)列中的一個(gè)線程,而會(huì)通知等待隊(duì)列中的所有線程。 由上一篇文章你應(yīng)該已經(jīng)知道,在 破壞占用且等待條件 的時(shí)候,如果轉(zhuǎn)出賬本和轉(zhuǎn)入賬本不滿足同時(shí)在文件架上這個(gè)條件,就用死循環(huán)的方式來循環(huán)等待,核心代碼如下: // 一次性申請(qǐng)轉(zhuǎn)出賬戶和轉(zhuǎn)入賬戶,直到成功 while(!actr.apply...
閱讀 3777·2023-04-25 20:00
閱讀 3122·2021-09-22 15:09
閱讀 519·2021-08-25 09:40
閱讀 3429·2021-07-26 23:38
閱讀 2214·2019-08-30 15:53
閱讀 1103·2019-08-30 13:46
閱讀 2801·2019-08-29 16:44
閱讀 2056·2019-08-29 15:32