Java synchronized應用入門

在學習 synchronized 的使用時的一點小總結和應用給大家分享一下.

 

在使用synchronized關鍵字時有以下四點需要注意:

1. synchronized關鍵字不能繼承。

  雖然可以使用synchronized來定義方法,但synchronized並不屬於方法定義的一部分,因此,synchronized關鍵字不能被繼承。如果在父類中的某個方法使用了synchronized關鍵字,而在子類中覆蓋了這個方法,在子類中的這個方法默認情況下並不是同步的,而必須顯式地在子類的這個方法中加上synchronized關鍵字纔可以。當然,還可以在子類方法中調用父類中相應的方法,這樣雖然子類中的方法不是同步的,但子類調用了父類的同步方法,因此,子類的方法也就相當於同步了。這兩種方式的例子代碼如下:

在子類方法中加上synchronized關鍵字

在子類方法中調用父類的同步方法

 

2. 在定義接口方法時不能使用synchronized關鍵字。

3. 構造方法不能使用synchronized關鍵字,但可以使用下節要討論的synchronized塊來進行同步。

4. synchronized可以自由放置。

 

在前面的例子中使用都是將synchronized關鍵字放在方法的返回類型前面。但這並不是synchronized可放置唯一位置。在非靜態方法中,synchronized還可以放在方法定義的最前面,在靜態方法中,synchronized可以放在static的前面,代碼如下:

 

但要注意,synchronized不能放在方法返回類型的後面,如下面的代碼是錯誤的:

 

synchronized關鍵字只能用來同步方法,不能用來同步類變量,如下面的代碼也是錯誤的。

 

 

 

雖然使用synchronized關鍵字同步方法是最安全的同步方式,但大量使用synchronized關鍵字會造成不必要的資源消耗以及性能損失。雖然從表面上看synchronized鎖定的是一個方法,但實際上synchronized鎖定的是一個類。也就是說,如果在非靜態方法method1和method2定義時都使用了synchronized,在method1未執行完之前,method2是不能執行的。靜態方法和非靜態方法的情況類似。但靜態和非靜態方法不會互相影響。看看如下的代碼:

 

運行結果如下:

  非靜態的method1方法

  靜態的method3方法

  從上面的運行結果可以看出,method2和method4在method1和method3未結束之前不能運行。因此,我們可以得出一個結論,如果在類中使用synchronized關鍵字來定義非靜態方法,那將影響這個中的所有使用synchronized關鍵字定義的非靜態方法。如果定義的是靜態方法,那麼將影響類中所有使用synchronized關鍵字定義的靜態方法。這有點象數據表中的表鎖,當修改一條記錄時,系統就將整個表都鎖住了,因此,大量使用這種同步方式會使程序的性能大幅度下降。

 

 

---------------------------------------------------------------------------------------------

一點多線程同步共享資源的互斥訪問的誤區

 

Java多線程的同步依靠的是對象鎖機制,synchronized關鍵字的背後就是利用了封鎖來實現對共享資源的互斥訪問。

在run()的調用方法中加入了synchronized關鍵字,希望能對run方法進行互斥訪問,從使用的角度來看貌似是實現了同步,但並沒有達到目的,這是因爲這裏synchronized鎖住的是this對象,即當前運行線程對象本身。Java多線程代碼中創建了10個線程,而每個線程都持有this對象的對象鎖,這不能實現線程的同步。

改進方式:

在run()調用的方法taskHandler中加上static 聲明, synchronized關鍵字就會鎖定靜態類的實例對象, 線程是互斥訪問的, 這樣就可以達到線程的同步要求了。代碼如下:

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