摘要: synchronized ()方法解決了線程同步的問題,卻帶來新的問題——線程死鎖。線程死鎖是多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。 public class sisuo { public s
synchronized ()方法解決了線程同步的問題,卻帶來新的問題——線程死鎖。線程死鎖是多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。
public class sisuo { public static void main(String[] args) { Object obj1=new Object(); Object obj2=new Object(); DeadLockThread1 diedLock1=new DeadLockThread1(obj1,obj2); DeadLockThread2 diedLock2=new DeadLockThread2(obj1,obj2); diedLock1.start(); diedLock2.start(); } } class DeadLockThread1 extends Thread{ private Object obj1; private Object obj2; public DeadLockThread1(Object obj1,Object obj2){ this.obj1=obj1; this.obj2=obj2; } public void run() { synchronized (obj1) { try{ Thread.sleep(100); synchronized (obj2) { System.out.println("Thread1執(zhí)行成功"); } }catch (InterruptedException e) { e.printStackTrace(); } } } } class DeadLockThread2 extends Thread{ private Object obj1; private Object obj2; public DeadLockThread2(Object obj1,Object obj2){ this.obj1=obj1; this.obj2=obj2; } public void run() { synchronized (obj2) { try{ Thread.sleep(100); synchronized(obj1) { System.out.println("Thread2執(zhí)行成功"); } }catch (InterruptedException e) { e.printStackTrace(); } } } }
在這個例子中,線程1和線程2同時啟動。線程1鎖定了obj1并等待obj2釋放, 線程2鎖定了obj2并等待obj1釋放,因此陷入死循環(huán),無法得出執(zhí)行結果。由于時間片隨機分配,死鎖并非一定發(fā)生,尤其當程序語句并不多的時候,可能線程1執(zhí)行完后才執(zhí)行線程2,從而運行成功。但本例中在兩個步驟之間加入Thread.sleep(100);設置0.1秒的休息時間,死鎖必然會發(fā)生。
java沒有檢測死鎖的機制,因此在設計時一定要合理避免死鎖。如果把class DeadLockThread2的synchronized (obj1)和synchronized (obj2)調(diào)換順序就能看到執(zhí)行結果:
避免死鎖最簡單的方法就是設置相同的訪問順序或在所有線程的第一部添加一把相同的鎖。雖然這樣會減緩程序的運行時間,消耗更多的資源。