java線程同步原理、wait,notify的用法及與sleep的區別

一。 java線程同步原理

java會爲每個object對象分配一個monitor,當某個對象的同步方法(synchronized methods )或同步快被多個線程調用時,該對象的monitor將負責處理這些訪問的併發獨佔要求。
當一個線程調用一個對象的同步方法時,JVM會檢查該對象的monitor。如果monitor沒有被佔用,那麼這個線程就得到了monitor的佔有權,可以繼續執行該對象的同步方法;如果monitor被其他線程所佔用,那麼該線程將被掛起,直到monitor被釋放。
當線程退出同步方法調用時,該線程會釋放monitor,這將允許其他等待的線程獲得monitor以使對同步方法的調用執行下去。
注意:java對象的monitor機制和傳統的臨界檢查代碼區技術不一樣。java的一個類一個同步方法並不意味着同時只有一個線程獨佔執行(不同對象的同步方法可以同時執行),但臨界檢查代碼區技術確會保證同步方法在一個時刻只被一個線程獨佔執行。

java的monitor機制的準確含義是:任何時刻,對一個指定object對象的某同步方法只能由一個線程來調用。
java對象的monitor是跟隨object實例來使用的,而不是跟隨程序代碼。兩個線程可以同時執行相同的同步方法,比如:一個類的同步方法是xMethod(),有a,b兩個對象實例,一個線程執行a.xMethod(),另一個線程執行b.xMethod(). 互不衝突。

二。 wait()、notify(),notifyAll()的使用
obj.wait()方法使本線程掛起,並釋放obj對象的monitor,只有其他線程調用obj對象的notify()或notifyAll()時,纔可以被喚醒。
obj.notifyAll()方法喚醒所有阻塞在obj對象上的沉睡線程,然後被喚醒的衆多線程競爭obj對象的monitor佔有權,最終得到的那個線程會繼續執行下去,但其他線程繼續等待。
obj.notify()方法是隨機喚醒一個沉睡線程,過程更obj.notifyAll()方法類似。
wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,
如:
synchronized(x){
x.notify()
//或者wait()
}
以上內容說明了爲什麼調用wait(),notify(),notifyAll()的線程必須要擁有obj實例對象的monitor佔有權。
每個對象實例都有一個等待線程隊列。這些線程都是等待對該對象的同步方法的調用許可。對一個線程來說,有兩種方法可以進入這個等待線程隊列。一個是當其他線程執行同步方法時,自身同時也要執行該同步方法;另一個是調用obj.wait()方法。
當同步方法執行完畢或者執行wait()時,其他某個線程將獲得對象的訪問權。當一個線程被放入等待隊列時,必須要確保可以通過notify()的調用來解凍該線程,以使其能夠繼續執行下去。

三。 wait()與sleep()的區別
sleep()方法是Thread類的靜態方法,不涉及到線程間同步概念,僅僅爲了讓一個線程自身獲得一段沉睡時間。sleep可以在任何地方使用。
wait()方法是object類的方法,解決的問題是線程間的同步,該過程包含了同步鎖的獲取和釋放,調用wait方法將會將調用者的線程掛起,直到其他線程調用同一個對象的notify()方法纔會重新激活調用者。
注意:線程調用notify()之後,只有該線程完全從 synchronized代碼裏面執行完畢後,monitor纔會被釋放,被喚醒線程纔可以真正得到執行權。

發佈了52 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章