簡體   English   中英

如何使用synchronized鎖定整個類的方法?

[英]How to lock a method for a whole class using synchronized?

我知道當你想要鎖定方法時只用一個線程來執行你用synchronized關鍵字聲明它。

那么類,當線程在該類的實例上執行某些代碼時,如何提供對整個對象類的鎖定呢?

換句話說,當一個線程在一個對象上執行一個方法時,即使在同一個類的不同實例上也不應該允許其他線程執行相同的方法。

您在特定對象上同步,可以是某個指定的靜態鎖定對象,也可以是類對象(當聲明靜態方法被同步時會發生):

class X {
    private static final Object lock = new Object();
    public void oneAtATime() {
        synchronized (lock) {
            // Do stuff
        }
    }
}
class Y {
    public void oneAtATime() {
        synchronized (Y.class) {
            // Do stuff
        }
    }
}

每個變體都有自己的優點和缺點; 鎖定類允許類之外的其他代碼出於其自身原因使用相同的鎖(這允許它協調比您提供的更高級別的同步),而static final Object lock方法允許您通過使鎖定字段保密(這使得更容易推斷鎖定並避免代碼死鎖,因為其他人編寫了錯誤的代碼)。

您當然也可以使用java.util.concurrent一些同步機制,例如顯式Lock ,它提供對鎖定的更多控制(並且ReentrantLock當前比高爭用下的隱式鎖定執行得更好)。


編輯:請注意,靜態/全局鎖定不是一個好方法 - 這意味着所創建的類的每個實例都將基本上綁定到每個其他實例(除了使測試或讀取代碼更加困難之外,嚴重損害可擴展性)。 我假設你這樣做是為了同步某種全局狀態? 在這種情況下,我會考慮在類中包裝該全局/靜態狀態,並實現每個實例的同步而不是全局。

而不是像這樣的東西:

class Z {
    private static int state;
    public void oneAtATime(){
        synchronized (Z.class) {
            state++;
        }
    }
}

像這樣做:

class State {
    private int value;
    public synchronized void mutate(){ value++; }
}
class Z {
    private final State state;
    public Z(State state){
        this.state = state;
    }
    public void oneAtATime(){
        state.mutate();
    }
}
// Usage:
State s1 = new State(), s2 = new State();
Z foo = new Z(s1);
Z bar = new Z(s1);
Z frob = new Z(s2);
Z quux = new Z(s2);

現在foobar仍然相互聯系,但他們可以獨立於frobquux

如果使用靜態同步方法,則通過類鎖定鎖定它們。 你也可以在類中聲明一個靜態Object,並在我相信的方法中將其鎖定,例如:

private static final Object STATIC_LOCK = new Object();

private void foo() {
     synchronized (STATIC_LOCK) {
          //do stuff...
     } 
}

您可以在該方法中使用靜態Mutex 所以任何並發線程都在方法內阻塞,而另一個並發運行它,無論它屬於哪個類的對象。 我不認為有任何特殊的單一關鍵字可以產生像synchronized一樣的效果。

這是一個相當積極的同步,我會盡可能地避免它。

在類的靜態字段或類本身上同步:

synchronized(MyClass.class) {
        // mutually excluded method body
}

兩個線程都必須使用這種結構

public void someMethod() {
  synchronized(ClassThatShouldBeProtected.class) {
    someSynchronizedCode();
  }
}

這種方法得益於這樣一個事實,即類本身是一個對象,因此它有一個監視器。 那你就不需要任何人工靜態實例了。

沒有內置的機制。 創建自己的靜態鎖屬性,並確保鎖定它並在每種方法中解鎖它。 不要忘記異常 - 確保在“finally”部分解鎖。

這應該工作:

public class MyClass {
  void synchronizedMethod() {
    synchronized (MyClass.class) {
       // synchronized on static level
    }
  }
}

哪個'錯過'類的鎖定運行時表示。 這是可能的,因為任何對象都可以用作Java中的互斥鎖。

http://www.janeg.ca/scjp/threads/synchronization.html

談談實現它的幾種方法。 通常,鎖是禁止的並且阻礙了線程的好處。 因此,關鍵代碼應盡量減少。

你想要一個類杠桿鎖來訪問類的靜態變量,還是要保護對類的公共外部資源的訪問? 在這種情況下,您應該在訪問它時有一個單獨的鎖。

暫無
暫無

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

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