網頁

2017/10/12

Java 執行緒 synchronized method deadlock

當執行緒呼叫物件的同步方法(synchronized method)時,執行緒取得該物件的鎖,直到方法執行結束後才會釋放。


下面範例演示了使用synchronized method時造成的deadlock。

Friend類別,hi()hiBack()皆宣告為synchronized method

Friend

public class Friend {
  
  private String name;
  
  public Friend(String name){
    this.name = name;
  }
  
  public synchronized void hi(Friend friend){
    String threadName = Thread.currentThread().getName();
    System.out.println(threadName + ":" + this.name + ":" + friend.getName() + "甲霸沒?");
    friend.hiBack(this);
  }
  
  public synchronized void hiBack(Friend friend){
    System.out.println(this.name + ":" + "挖甲霸阿,恁勒?");
    
  }
  
  public String getName(){
    return this.name;
  }

}

執行時,宣告兩個執行緒thread-athread-b,分別呼叫Friend物件的synchronized method。

public class Test {

  public static void main(String[] args) {
    
    Friend ming = new Friend("小明");
    Friend hua = new Friend("大華");
    
    Thread a = new Thread(() -> { // Runnable.run()
      ming.hi(hua); // 取得ming的鎖
    }, "thread-a");
    
    Thread b = new Thread(() -> { // Runnable.run()
      hua.hi(ming); // 取得hua的鎖 
    }, "thread-b");
    
    a.start();
    b.start();
    
  }
}

thread-a呼叫ming.hi(hua)時取得ming的鎖,同樣地thread-b呼叫hua.hi(ming)時,取得hua的鎖。當thread-a要執行hi()中的friend.hiBack(this)時,因為friend物件的實例為hua,但此時huathread-b鎖定,因此必須等待thread-b執行完hi()方法並釋放鎖才會執行,然而同樣地thread-b要執行hi()中的friend.hiBack(this)時也是必須等待thread-a執行完hi()方法並釋放鎖才會執行,因此形成了兩條執行緒互相等待的deaklock。


沒有留言:

張貼留言