標籤:
管程的概念
管程 (英語:Moniters,也稱為監視器) 是一種程式結構,結構內的多個子程式(對象或模組)形成的多個背景工作執行緒互斥訪問共用資源。 這些共用資源一般是硬體裝置或一群變數。管程實現了在一個時間點,最多隻有一個線程在執行管程的某個子程式。 與那些通過修改資料結構實現互斥訪問的並發程式設計相比,管程實現很大程度上簡化了程式設計。 管程提供了一種機制,線程可以臨時放棄互斥訪問,等待某些條件得到滿足後,重新獲得執行權恢複它的互斥訪問。
一個管程包含:
- 多個彼此可以互動並共用資源的線程
- 多個與資源使用有關的變數
- 一個互斥鎖
- 一個用來避免競態條件的不變數
一個管程的程式在運行一個線程前會先取得互斥鎖,直到完成線程或是線程等待某個條件被滿足才會放棄互斥鎖。 若每個執行中的線程在放棄互斥鎖之前都能保證不變數成立,則所有線程皆不會導致競態條件成立。 當一個線程執行管程中的一個子程式時,稱為佔用(occupy)該管程. 管程的實現確保了在一個時間點,最多隻有一個線程佔用了該管程。這是管程的互斥鎖訪問性質。 當線程要調用一個定義在管程中的子程式時,必須等到已經沒有其它線程在執行管程中的某個子程式。 在管程的簡單實現中,編譯器為每個管程對象自動加入一把私人的互斥鎖。該互斥鎖初始狀態為解鎖, 在管程的每個公用子程式的入口給該互斥鎖加鎖,在管程的每個公用子程式的出口給該互斥鎖解鎖。
條件變數(Condition Variable)
管程提供了一種實現互斥的簡便途徑,但這還不夠。我們還需要一種辦法使得線程在無法繼續運行時被阻塞。 在生產者-消費者問題中,很容易將針對緩衝區滿和緩衝區空的測試放到管程過程中,但是生產者在發現緩衝區滿的時候如何阻塞呢? 解決的方法是引入條件變數(condition variables)以及相關的兩個操作:wait和signal。 當一個管程過程發現它無法繼續運行時(例如,生產者發現緩衝區滿),它會在某個條件變數上(如full)執行wait操作。 該操作導致調用進程自身阻塞,並且還將另一個以前等在管程之外的進程調入管程。 另一個線程,比如消費者,可以喚醒正在睡眠的夥伴進程,這可以通過對其夥伴正在等待的一個條件變數執行signal完成。 為了避免管程中同時有兩個活躍進程,如果在一個條件變數上有若干進程正在等待,則在對該條件變數執行signal操作後, 系統發送器只能在其中選擇一個使其恢複運行。
線程可能需要等待某個條件P為真,才能繼續執行。在一個忙等待(busy waiting)迴圈中 while not( P ) do skip 將會導致所有其它進程都無法進入臨界區使得該條件P為真,該管程發生死結. 解決辦法是條件變數(condition variables). 概念上,一個條件變數就是一個線程隊列(queue), 其中的線程正等待某個條件變為真。 每個條件變數c關聯著一個斷言P_c. 當一個線程等待一個條件變數,該線程不算作佔用了該管程,因而其它線程可以進入該管程執行, 改變管程的狀態,通知條件變數c其關聯的斷言P_c在目前狀態下為真.
因此對條件變數存在兩種主要操作: wait c 被一個線程調用,以等待斷言P_c被滿足後該線程可恢複執行. 線程掛在該條件變數上等待時,不被認為是佔用了管程. signal c (有時寫作notify c)被一個線程調用,以指出斷言P_c現在為真. 當一個通知(signal)發給了一個有線程處於等待中的條件變數,則有至少兩個線程將要佔用該管程: 發出通知的線程與等待該通知的某個線程. 只能有一個線程佔用該管程,因此必須做出選擇。兩種理論體系導致了兩種不同的條件變數的實現: 阻塞式條件變數(Blocking condition variables),把優先順序給了被通知的線程. 非阻塞式條件變數(Nonblocking condition variables),把優先順序給了發出通知的線程.
隱式條件變數管程
Java程式設計語言中,每個對象都可以作為一個管程。需要互斥使用的方法必須明確標示關鍵字synchronized. 代碼塊也可以標示關鍵字synchronized. 不使用明確的條件變數, Java的這種管程在入口隊列之外,使用單獨的條件等待隊列. 所有等待的線程進入這個隊列, 所有的notify與notify all操作也施加於這個隊列。這種方法已經被其它程式設計語言使用,如C#.
Java中的同步方法與其他經典管程有本質差別:Java沒有內嵌的條件變數。反之,Java提供了兩個過程wait和notify ,分別與sleep和wakeup等價, 不過,當它們在同步方法中使用時,它們不受競爭條件約束。理論上,方法wait可以被中斷,它本身就是與中斷有關的代碼。Java需要顯式表示異常處理。
java企業級通用許可權安全架構源碼 SpringMVC mybatis or hibernate+ehcache shiro druid bootstrap HTML5
【java架構源碼下載】
Java對管程的支援