java線程實現同步的方式

1、同步方法

使用synchronized關鍵字修飾的方法。 由於java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處於阻塞狀態。

注: synchronized關鍵字也可以修飾靜態方法,此時如果調用該靜態方法,將會鎖住整個類。

2、同步代碼塊

synchronized關鍵字修飾的語句塊。被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步

使用synchronized(this)格式來同步代碼塊(synchronized(this):當前對象:當一個類加到內存時,常量池有一個地址直接指向當前正在執行的對象.)

其實Java還支持對“任意對象”作爲“對象監視器”來實現同步的功能。這個“任意對象”大多數是實例變量及方法的參數,使用格式爲synchronized(非this對象),非this對象即同步監視器,相當於鎖的鑰匙,同步監視器的目的就是爲了阻止兩個線程對同一個共享資源進行併發訪問,因此通常推薦使用可能被併發訪問的共享資源充當同步監視器。

鎖非this對象具有一定的優點:如果一個類中有很多個synchronized方法,這時雖然能實現同步,但會受到阻塞,所以影響消息;但如果使用同步代碼塊鎖非this對象,則synchronized(非this)代碼塊的程序與同步方法是異步的。不與其他鎖this同步方法爭搶this鎖,則可以大大提高運行效率。

注:同步是一種高開銷的操作,因此應該儘量減少同步的內容。通常沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼即可。

3、重入鎖方式

在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現了Lock接口的鎖, 它與使用synchronized方法和快具有相同的基本行爲和語義,並且擴展了其能力。
         ReenreantLock類的常用方法有:
         ReentrantLock() : 創建一個ReentrantLock實例 
         lock() : 獲得鎖 
         unlock() : 釋放鎖 
   
 注:ReentrantLock()還有一個可以創建公平鎖的構造方法,但由於能大幅度降低程序運行效率,不推薦使用 
4、使用ThreadLocal

如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本,副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產生影響。

ThreadLocal與同步機制 
a.ThreadLocal與同步機制都是爲了解決多線程中相同變量的訪問衝突問題
b.前者採用以"空間換時間"的方法,後者採用以"時間換空間"的方式
 
5、使用特殊域變量volatile實現線程同步

    a.volatile關鍵字爲域變量的訪問提供了一種免鎖機制
    b.使用volatile修飾域相當於告訴虛擬機該域可能會被其他線程更新
    c.因此每次使用該域就要重新計算,而不是使用寄存器中的值 
    d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變量 
6、Object基礎類中的方法

wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。

sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
Allnotity():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
當需要調用以上的方法的時候,一定要對競爭資源進行加鎖,如果不加鎖的話,則會報 IllegalMonitorStateException 異常

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