Java併發監視器-Monitor

一、閱讀本文須知

  • 信號量(Semaphore):在多線程環境下使用的一種設施,可以用來保證兩個或多個關鍵代碼段不被併發調用。在進入一個關鍵代碼段之前,線程必須獲取一個信號量;一旦該關鍵代碼段完成了,那麼該線程必須釋放信號量。其它想進入該關鍵代碼段的線程必須等待直到第一個線程釋放信號量。
  • 互斥量(Mutex):又稱爲互斥鎖,每個對象都對應於一個可稱爲" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。

二、Monitor的特性

  • 互斥:Monitor 最重要的特點是,同一個時刻,只有一個 線程能進入 monitor 中定義的臨界區,這使得 monitor 能夠達到互斥的效果。
  • 信號量:僅僅有互斥的作用是不夠的,無法進入 monitor 臨界區的線程,它們應該被阻塞,並且在必要的時候會被喚醒。顯然,monitor 作爲一個同步工具,也應該提供這樣的管理線程狀態的機制。想想我們爲什麼覺得 信號量 和 互斥 在編程上容易出錯,因爲我們需要去親自操作變量以及對 線程 進行阻塞和喚醒。monitor 這個機制之所以被稱爲“更高級的原語”,是因爲它對外屏蔽掉了這些機制,使得使用 monitor 的人看到的是一個簡潔易用的接口。

三、實現Monitor的三要素

1、臨界區
2、monitor 對象及鎖
3、條件變量以及定義在 monitor 對象上的 wait、signal 操作。

  • 互斥:使用 monitor 機制的目的主要是爲了互斥進入臨界區,爲了做到能夠阻塞無法進入臨界區的線程,需要通過一個基於互斥量的鎖和一個 monitor object 來協助完成,這個 monitor object 內部會有相應的數據結構,例如列表,來保存被阻塞的線程。
  • 信號量:爲了在適當的時候能夠阻塞和喚醒線程,需要引入一個條件變量用來決定什麼時候是“適當的時候”,這個條件可以來自程序代碼的邏輯,也可以是在 monitor object 的內部,總而言之,程序員對條件變量的定義有很大的自主性。不過,由於 monitor object 內部採用了數據結構來保存被阻塞的隊列,因此它也必須對外提供兩個 API 來讓線程進入阻塞狀態以及之後被喚醒,分別是 wait 和 notify。

四、Java中Monitor的實現

1、臨界區:被 synchronized 關鍵字修飾的方法、代碼塊,就是 monitor 機制的臨界區。
2、monitor 對象及鎖:synchronized 關鍵字在使用的時候,往往需要指定一個對象與之關聯,例如 synchronized(this),synchronized 如果修飾的是實例方法,那麼其關聯的對象實際上是 this,如果修飾的是類方法,那麼其關聯的對象是 this.class。總之,synchronzied 需要關聯一個對象,而這個對象就是 monitor object。
3、條件變量以及定義在 monitor 對象上的 wait、signal 操作:
wait、signal 操作:java.lang.Object 類定義了 wait(),notify(),notifyAll() 方法
條件變量:Java 對象存儲在內存中,分別分爲三個部分,即對象頭、實例數據和對齊填充,而在其對象頭中,保存了鎖標識,wait、signal 操作會改變條件進而改變鎖標識的狀態

注:本文所有內容僅供參考,如有錯誤,還望指出

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