synchronized關鍵字有兩種用法第一種就是在《使用Synchronized關鍵字同步類方法》一文中所介紹的直接用在方法的定義中另外一種就是synchronized塊我們不僅可以通過synchronized塊來同步一個對象變量也可以使用synchronized塊來同步類中的靜態方法和非靜態方法
synchronized塊的語法如下
public void method()
{
… …
synchronized(表達式)
{
… …
}
}
一非靜態類方法的同步
從《使用Synchronized關鍵字同步類方法》一文中我們知道使用synchronized關鍵字來定義方法就會鎖定類中所有使用synchronzied關鍵字定義的靜態方法或非靜態方法但這並不好理解而如果使用synchronized塊來達到同樣的效果就不難理解為什麼會產生這種效果了如果想使用synchronized塊來鎖定類中所有的同步非靜態方法需要使用this做為synchronized塊的參數傳入synchronized塊國代碼如下
通過synchronized塊同步非靜態方法
public class SyncBlock
{
public void method()
{
synchronized(this) // 相當於對method方法使用synchronized關鍵字
{
… …
}
}
public void method()
{
synchronized(this) // 相當於對method方法使用synchronized關鍵字
{
… …
}
}
public synchronized void method()
{
… …
}
}
在上面的代碼中的method和method方法中使用了synchronized塊而第行的method方法仍然使用synchronized關鍵字來定義方法在使用同一個SyncBlock類實例時這三個方法只要有一個正在執行其他兩個方法就會因未獲得同步鎖而被阻塞在使用synchronized塊時要想達到和synchronized關鍵字同樣的效果必須將所有的代碼都寫在synchronized塊中否則將無法使當前方法中的所有代碼和其他的方法同步
除了使用this做為synchronized塊的參數外還可以使用SyncBlockthis作為synchronized塊的參數來達到同樣的效果
在內類(InnerClass)的方法中使用synchronized塊來時this只表示內類和外類(OuterClass)沒有關系但內類的非靜態方法可以和外類的非靜態方法同步如在內類InnerClass中加一個method方法並使method方法和SyncBlock的三個方法同步代碼如下
使內類的非靜態方法和外類的非靜態方法同步
public class SyncBlock
{
… …
class InnerClass
{
public void method()
{
synchronized(SyncBlockthis)
{
… …
}
}
}
… …
}
在上面SyncBlock類的新版本中InnerClass類的method方法和SyncBlock類的其他三個方法同步因此methodmethodmethod和method四個方法在同一時間只能有一個方法執行
Synchronized塊不管是正常執行完還是因為程序出錯而異常退出synchronized塊當前的synchronized塊所持有的同步鎖都會自動釋放因此在使用synchronized塊時不必擔心同步鎖的釋放問題
二靜態類方法的同步
由於在調用靜態方法時對象實例不一定被創建因此就不能使用this來同步靜態方法而必須使用Class對象來同步靜態方法代碼如下
通過synchronized塊同步靜態方法
public class StaticSyncBlock
{
public static void method()
{
synchronized(StaticSyncBlockclass)
{
… …
}
}
public static synchronized void method()
{
… …
}
}
在同步靜態方法時可以使用類的靜態字段class來得到Class對象在上例中method和method方法同時只能有一個方法執行除了使用class字段得到Class對象外還可以使用實例的getClass方法來得到Class對象上例中的代碼可以修改如下
使用getClass方法得到Class對象
public class StaticSyncBlock
{
public static StaticSyncBlock instance;
public StaticSyncBlock()
{
instance = this;
}
public static void method()
{
synchronized(instancegetClass())
{
}
}
}
在上面代碼中通過一個public的靜態instance得到一個StaticSyncBlock類的實例並通過這個實例的getClass方法得到了Class對象(一個類的所有實例通過getClass方法得到的都是同一個Class對象因此調用任何一個實例的getClass方法都可以)我們還可以通過Class對象使不同類的靜態方法同步如Test類的靜態方法method和StaticSyncBlock類的兩個靜態方法同步代碼如下
Test類的method方法和StaticSyncBlock類的methodmethod方法同步
public class Test
{
public static void method()
{
synchronized(StaticSyncBlockclass)
{
}
}
}
注意在使用synchronized塊同步類方法時非靜態方法可以使用this來同步而靜態方法必須使用Class對象來同步它們互不影響當然也可以在非靜態方法中使用Class對象來同步靜態方法但在靜態方法中不能使用this來同步非靜態方法這一點在使用synchronized塊同步類方法時應注意
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27374.html