2010-10-12 59 views
3

當我使用同步方法over實例方法監視器與'this'關聯,另一方面當我在我的類(靜態)方法上同步監視器與類對象關聯什麼情況下,如果我有一個靜態變量用於非靜態方法?會同步嗎?當在同步方法或java中使用靜態成員

public class A{ 

    public static int reg_no = 100; 

    public synchronized void registration(){ 

     A.reg_no = some operation... 

    } 

} 
在上述情況下

會發生什麼靜態變量reg_no如果兩個或多個線程爭奪法註冊()

回答

2

使用​​註釋成員函數時,該方法在對象的實例上同步。

public synchronized void registration() { 
    synchronized (A.class) { 
     A.reg_no = some operation ... 
    } 
} 

注意的是,上述獲得兩把鎖,這可能會導致deadlocks如果任何其他代碼獲得相同的兩個鎖:如果你想在一個靜態變量同步,您必須手動將類對象上同步以其他順序。您可能希望從該方法中刪除​​,只留下synchronized (A.class)

1

訪問變量(靜態或實例)不同步。該方法的同步將防止單個實例的競態條件,而不管變量(靜態或實例)如何。如果要防範多個實例,則必須在類文字上進行同步,但這看起來很真實錯誤。

+0

單獨的方法同步不*防止可能的併發訪問'靜態'變量,特別是如果有靜態方法,也可能會修改靜態變量。 – 2010-10-12 09:23:55

+0

這就是我所說的。它只會保護該方法的多個調用。不是其他人。但他的例子並沒有說明其他人是否可以訪問它。 – Bozho 2010-10-12 09:26:09

0

不,你需要將方法同步到類,例如。 synchronized(A.class)

0

而不是在syncronized方法內部添加另一個syncronized塊如果您的問題是與其他線程共享該變量,我會聲明靜態變量爲volatile。

1

(一些進一步的思考後經修訂)

對於你上面介紹可以宣佈你的靜態INT揮發,朋克樂隊建議跑不掉的例子。

然而,在一般情況下 - 例如,如果你的靜態可變用的可變狀態的對象...

的同步實例方法意味着只有線保持物體實例鎖被允許在進步該類的實例的方法,並且當線程在方法中完成並釋放鎖時,任何其他線程使用同一個鎖進入任何同步塊將「看到」您所做的更改。

防止被另一個線程其中靜態變量正在作出改變:

  • 新值從外部直接A級分配給靜態變量(該變量是公開的!)
  • 調用哪個重新分配靜態變量,因爲它會使用不同的鎖定
  • 類A的一個靜態方法(同步或以其他方式)調用類A

的非同步實例方法,使用同步方法通常是有點危險 - 它們可以導致死鎖,因爲鎖可以由使用你的類/實例作爲同步塊的目標其他代碼外採取:

synchronized (objectOfTypeA) { ... } // takes the instance lock 

synchronized (A.getClass()) { ... } // takes the class lock 

更好的方法可能是將靜態變量設置爲private,添加一個專用本地變量作爲鎖(因此它不能被鎖定在外部),並在方法的synchronized塊中使用專用本地鎖:

public class A { 

    private static int reg_no = 100; 
    private static Object lock = new Object(); 

    public void registration(){ 
     synchronized(lock) { 
      reg_no = some operation... 
     } 
    } 

    public static int getRegNo() { 
     synchronized(lock) { 
      return reg_no; 
     } 
    } 
} 
+0

靜態方法將無法在對象本地鎖定上同步。 – 2013-01-29 03:21:22