線程如何同步和通訊
阿新 • • 發佈:2017-07-07
zed 執行 ava 構造器 基本 指定時間 通訊 訪問 not
線程同步
什麽是線程同步?
線程同步的真實意思恰好相反,其實是“排隊”。當使用多個線程來訪問同一個數據時,非常容易出現線程安全問題(比如多個線程都在操作同一數據導致數據不一致),所以我們用同步機制來解決這些問題。
實現同步機制有兩個方法:
- 同步代碼塊:
synchronized(同一個數據/鎖){} 同一個數據:就是N條線程同時訪問一個數據。 - 同步方法:
public synchronized 數據返回類型 方法名(){}
同步方法的同步監視器(鎖)是 this 也就是該對象的本身通過使用同步方法,可非常方便的將某類變成線程安全的類。
線程安全的類:
- 這個類的對象可以同時被多個線程安全的訪問。
- 每個線程都能正常的執行原子操作,得到正確的結果。
- 在每個線程的原子操作都完成後,對象處於邏輯上合理的狀態。
註意:synchronized關鍵字可以修飾方法,也可以修飾代碼塊,但不能修飾構造器,屬性等。實現同步機制註意以下幾點: 安全性高,性能低,在多線程用。性能高,安全性低,在單線程用。
線程通訊:
為什麽要使用線程通訊?
當使用synchronized 來修飾某個共享資源時(分同步代碼塊和同步方法兩種情況),當某個線程獲得共享資源的鎖後就可以執行相應的代碼段,直到該線程運行完該代碼段後才釋放對該 共享資源的鎖,讓其他線程有機會執行對該共享資源的修改。當某個線程占有某個共享資源的鎖時,如果另外一個線程也想獲得這把鎖運行就需要使用wait() 和notify()/notifyAll()方法來進行線程通訊了。
wait():導致當前線程等待,直到其他線程調用同步監視器的notify方法或notifyAll方法來喚醒該線程。
wait(mills):都是等待指定時間後自動蘇醒,調用wait方法的當前線程會釋放該同步監視器的鎖定,可以不用notify或notifyAll方法把它喚醒。
notify():喚醒在同步監視器上等待的單個線程
notifyAll()方法:喚醒在同步監視器上等待的單個線程
同步鎖
線程同步的基本實現思路還是比較容易理解的。我們可以給共享資源加一把鎖,這把鎖只有一把鑰匙。哪個線程獲取了這把鑰匙,才有權利訪問該共享資源。
但是,現代的編程語言的設計思路都是把同步鎖加在代碼段上。確切的說,是把同步鎖加在“訪問共享資源的代碼段”上。這一點一定要記住,同步鎖是加在代碼段上的。
public static final Object lock1 = new Object(); … f1() { synchronized(lock1){ // lock1 是公用同步鎖 // 代碼段 A // 訪問共享資源 resource1 // 需要同步 } }
線程如何同步和通訊