天天看點

螢幕–JAVA同步基本概念

大學有一門課程叫作業系統,學習過的同學應該都記得,螢幕是作業系統實作同步的重要基礎概念,同樣它也用在java的線程同步中,這篇文章用一種類推的思想解釋螢幕”monitor”。

螢幕可以看做是經過特殊布置的建築,這個建築有一個特殊的房間,該房間通常包含一些資料和代碼,但是一次隻能一個消費者(thread)使用此房間,

螢幕–JAVA同步基本概念

當一個消費者(線程)使用了這個房間,首先他必須到一個大廳(entry set)等待,排程程式将基于某些标準(e.g. fifo)将從大廳中選擇一個消費者(線程),進入特殊房間,如果這個線程因為某些原因被“挂起”,它将被排程程式安排到“等待房間”,并且一段時間之後會被重新配置設定到特殊房間,按照上面的線路,這個建築物包含三個房間,分别是“特殊房間”、“大廳”以及“等待房間”。

螢幕–JAVA同步基本概念

簡單來說,螢幕用來監視線程進入這個特别房間,他確定同一時間隻能有一個線程可以通路特殊房間中的資料和代碼。

在java虛拟機中,每個對象(object和class)通過某種邏輯關聯螢幕,為了實作螢幕的互斥功能,每個對象(object和class)都關聯着一個鎖(有時也叫“互斥量”),這個鎖在作業系統書籍中稱為“信号量”,互斥(“mutex “)是一個二進制的信号量。

如果一個線程擁有了某些資料的鎖,其他的線程則無法獲得鎖,直到這個線程釋放了這個鎖。在多線程中,如果任何時候都是我們自己來寫這個信号量,顯然不是很友善,幸運的是,jvm為我們自動實作了這些。

為了使資料不被多個線程通路,java 提供了同步塊 以及 同步方法兩種實作,一旦一段代碼被嵌入到一個synchronized關鍵字中,意味着放入了監視區域,jvm在背景會自動為這段代碼實作鎖的功能。

我們知道java每個對象(object/class) 都關聯一個螢幕,更好的說法應該是每個對象(object/class)都有一個螢幕,對象可以有它自己的臨界區,并且能夠監視線程式列為了使線程協作,java為提供了wait()和notifyall以及notify()實作挂起線程,并且喚醒另外一個等待的線程,此外這些方法有三種不同版本:

<code>1</code>

<code>wait(</code><code>long</code> <code>timeout, </code><code>int</code> <code>nanos)</code>

<code>2</code>

<code>wait(</code><code>long</code> <code>timeout) notified by other threads or notified by timeout.</code>

<code>3</code>

<code>notify(all)</code>

這些方法隻能在一個同步塊或同步方法中被調用,原因是,如果一個方法不需要互相排斥,不需要監測或線程之間協作,每一個線程可以自由通路此方法,那就不需要協作。