閱讀481 返回首頁    go 阿裏雲 go 技術社區[雲棲]


監聽器-java同步的基本思想

如果你在大學學習過操作係統,你可能還記得監聽器在操作係統中是很重要的概念。同樣監聽器在java同步機製中也有使用,本文通過類比的方法來解釋“監聽器”的基本思想。

什麼是監聽器?

監聽器可以看成是包含了一間特殊房間的建築,這間特殊的房間在同一個時間隻能被一個客人(線程)擁有,通常這間房間包含了一些數據和代碼。

Java-Monitor

如果一個客人想擁有這間特殊的房間,他不得不首先在走廊(進入集)中等待著,然後調度器根據一些調度算法(eg:FIFO 先進先出)選擇一個。如果這個客人因為某些原因暫停懸掛著,則會被放到等待房間`,同時也被安排稍後重新進入這個特殊的房間,就像上麵圖片所展示的那樣,在這個建築裏有個3個房間。

java-monitor-associate-with-object

簡而言之:一個監聽器就是一個監聽線程進入這間特殊房間的設施。它確保了隻能有一個線程可以訪問這些受到保護的數據和代碼。

在java中監聽器是如何實現的?

在java虛擬機中,每個對象和類在邏輯上都和一個監聽器相關聯。為了實現監聽器的共同執行能力,鎖(有時候又叫互斥量)關聯著每個對象和類,在操作係統書上被稱之為“信號量”,互斥量其實就是一個二態的信號量。

如果一個線程拿到了相關數據的鎖,那麼其他線程不能再擁有這把鎖直到擁有這把鎖的線程釋放了這把鎖。當在多線程編程中,如果我們需要一直寫一個信號量這種方式可能會不太方便,幸運的是我們沒必要這麼做,因為JVM(java虛擬機)已經自動幫我們做了。

聲明一個監聽器區域,這意味著數據不能被超過一個線程訪問(譯者注:同時訪問的前提)。Java提供了同步的語句和同步的方法,一旦代碼嵌入到同步關鍵字內,這就是一個監聽器區域。而鎖是由jvm在底層自動實現的。

在java同步代碼中,哪部分才是監聽器?

我們知道每個對象/類都關聯著一個監聽器,我覺得這麼說好點,每個對象都擁有一個監聽器,因為每個對象都有它關鍵的區域和監聽線程隊列的能力。

為了使不同線程能相互合作,java提供了wait()和notify()方法來暫停一個線程和喚醒分別等待訪問這個對象的其他線程中的一個,另外還有3個其他版本:

wait(long timeout, int nanos)
wait(long timeout) notified by other threads or notified by timeout. 
notify(all)

這些方法隻能在一個同步語句或者同步方法內調用,原因是因為如果一個方法不要求互斥,那麼就沒有必要在線程間監聽或者是合作,每個線程都可以自由訪問這個方法。

這裏是一些同步代碼的例子。

參考資料
1. Java Doc for Object
2. Thread synchronization
3. Locks and Synchronization
4. notify() vs notifyAll()

 

最後更新:2017-05-23 17:32:20

  上一篇:go  Fork and Join: Java也可以輕鬆地編寫並發程序
  下一篇:go  什麼樣的網站建設公司才是值得信賴的?