簡體   English   中英

使用相同的鎖從另一個同步塊調用同步塊

[英]Calling a synchronized block from another synchronized block with same lock

我有這門課:

public class MyClass {

    public MyClass(){}

    public void actionA(){
        synchronized(MyClass.class){
            System.out.print("A");
        }
    }

    public void actionB(){
        synchronized(MyClass.class){
            actionA();
        }
    }

}

哪一個(如果有的話)是真的?

  1. 調用actionB()將導致死鎖,因為actionA()永遠不會獲取與MyClass.class關聯的鎖
  2. 調用actionB()不會導致死鎖,因為它已經獲取了與MyClass.class關聯的鎖

#2會發生,因為調用線程有鎖。

但是,如果代碼看起來像這樣:

public void actionB(){
    synchronized(MyClass.class) {
      Thread thread = new Thread(new Runnable { run() { actionA(); }});
      thread.start();
      thread.join();
    }
}

然后你會陷入僵局。 locks是基於每個線程獲取的。

我發現一個有用的心理圖片是掛鎖的共享密鑰。 一次只有一個線程可以擁有密鑰,但顯然相同的密鑰將打開它適合的任何鎖(該密鑰適合使用相同同步對象的任何鎖)。

順便說一句,在任何公開可見的字段上進行同步是不好的做法,因為遠程刪除的另一段代碼可能會可行地鎖定同一對象,從而導致不必要的爭用和可能的死鎖。

#2將會發生。

可重入同步

回想一下,線程無法獲取另一個線程擁有的鎖。 但是一個線程可以獲得它已經擁有的鎖。 允許線程多次獲取相同的鎖可啟用重入同步。 這描述了一種情況,其中同步代碼直接或間接地調用也包含同步代碼的方法,並且兩組代碼使用相同的鎖。 在沒有可重入同步的情況下,同步代碼必須采取許多額外的預防措施,以避免線程導致自身阻塞。

暫無
暫無

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

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