簡體   English   中英

在java中的synchronized方法或塊中使用靜態成員

[英]static members when used in synchronized method or block in java

當我在實例方法上使用synchronized方法時,監視器與'this'相關聯。 另一方面,當我在我的類(靜態)方法上進行同步時,監視器與類對象相關聯。 當我在非靜態方法中使用靜態變量時會發生什么? 會同步嗎?

例如,

public class A{

   public static int reg_no = 100;

   public synchronized void registration(){

      A.reg_no = some operation...

   }

}

在上面的例子中,如果兩個或多個線程競爭方法registration() ,靜態變量reg_no會發生什么?

使用synchronized注釋成員函數時,該方法將在對象的實例上同步。 如果要在靜態變量上進行同步,則必須手動同步類對象

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

請注意,上面獲得了兩個鎖,如果任何其他代碼在另一個順序中獲得相同的兩個鎖,則可能導致死鎖 您可能希望從方法中刪除synchronized ,只保留synchronized (A.class)

對變量(靜態或實例)的訪問不同步。 該方法的同步將防止單個實例的競爭條件,無論變量(靜態或實例)如何

如果你想要防范多個實例,你必須在類文字上進行同步,但這看起來確實是錯誤的。

(經過進一步思考后修改)

對於上面給出的示例,您可以通過聲明您的靜態int像punkers建議的那樣揮發。

但是在一般情況下 - 例如,如果你的靜態變量是一個具有可變狀態的對象......

synchronized實例方法意味着只允許持有對象實例鎖的線程在該類A實例的該方法中進行,並且當該線程在該方法中完成並釋放鎖時,任何其他線程使用任何其他線程進入任何同步塊相同的鎖將“看到”您所做的更改。

不會阻止被改變到另一個線程其靜態變量做:

  • 直接從外部類A為靜態變量賦值(變量是公共的!)
  • 調用類A的靜態方法(同步或其他),它重新分配靜態變量,因為它將使用不同的鎖
  • 調用A類的非同步實例方法

使用synchronized方法通常有點危險 - 它們可能導致死鎖,因為鎖可以由其他使用您的類/實例作為同步塊的目標的代碼從外部獲取:

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

要么

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

更好的方法可能是將靜態變量設為私有,添加私有本地變量以用作鎖(因此無法在外部鎖定),並在方法中的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;
        }
    }
}

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM