Java并发编程(9):死锁(含代码)
當線程需要同時持有多個鎖時,有可能產生死鎖。考慮如下情形:
線程A當前持有互斥所鎖lock1,線程B當前持有互斥鎖lock2。接下來,當線程A仍然持有lock1時,它試圖獲取lock2,因為線程B正持有lock2,因此線程A會阻塞等待線程B對lock2的釋放。如果此時線程B在持有lock2的時候,也在試圖獲取lock1,因為線程A正持有lock1,因此線程B會阻塞等待A對lock1的釋放。二者都在等待對方所持有鎖的釋放,而二者卻又都沒釋放自己所持有的鎖,這時二者便會一直阻塞下去。這種情形稱為死鎖。
下面給出一個兩個線程間產生死鎖的示例,如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | public class Deadlock extends Object { ????private String objID; ????public Deadlock(String id) { ????????objID = id; ????} ????public synchronized void checkOther(Deadlock other) { ????????print("entering checkOther()"); ????????try { Thread.sleep(2000); } ????????catch ( InterruptedException x ) { } ????????print("in checkOther() - about to " + "invoke 'other.action()'"); ????????//調用other對象的action方法,由于該方法是同步方法,因此會試圖獲取other對象的對象鎖 ????????other.action(); ????????print("leaving checkOther()"); ????} ????public synchronized void action() { ????????print("entering action()"); ????????try { Thread.sleep(500); } ????????catch ( InterruptedException x ) { } ????????print("leaving action()"); ????} ????public void print(String msg) { ????????threadPrint("objID=" + objID + " - " + msg); ????} ????public static void threadPrint(String msg) { ????????String threadName = Thread.currentThread().getName(); ????????System.out.println(threadName + ": " + msg); ????} ????public static void main(String[] args) { ????????final Deadlock obj1 = new Deadlock("obj1"); ????????final Deadlock obj2 = new Deadlock("obj2"); ????????Runnable runA = new Runnable() { ????????????????public void run() { ????????????????????obj1.checkOther(obj2); ????????????????} ????????????}; ????????Thread threadA = new Thread(runA, "threadA"); ????????threadA.start(); ????????try { Thread.sleep(200); } ????????catch ( InterruptedException x ) { } ????????Runnable runB = new Runnable() { ????????????????public void run() { ????????????????????obj2.checkOther(obj1); ????????????????} ????????????}; ????????Thread threadB = new Thread(runB, "threadB"); ????????threadB.start(); ????????try { Thread.sleep(5000); } ????????catch ( InterruptedException x ) { } ????????threadPrint("finished sleeping"); ????????threadPrint("about to interrupt() threadA"); ????????threadA.interrupt(); ????????try { Thread.sleep(1000); } ????????catch ( InterruptedException x ) { } ????????threadPrint("about to interrupt() threadB"); ????????threadB.interrupt(); ????????try { Thread.sleep(1000); } ????????catch ( InterruptedException x ) { } ????????threadPrint("did that break the deadlock?"); ????} } |
運行結果如下:
從結果中可以看出,在執行到other.action()時,由于兩個線程都在試圖獲取對方的鎖,但對方都沒有釋放自己的鎖,因而便產生了死鎖,在主線程中試圖中斷兩個線程,但都無果。
大部分代碼并不容易產生死鎖,死鎖可能在代碼中隱藏相當長的時間,等待不常見的條件地發生,但即使是很小的概率,一旦發生,便可能造成毀滅性的破壞。避免死鎖是一件困難的事,遵循以下原則有助于規避死鎖:
1、只在必要的最短時間內持有鎖,考慮使用同步語句塊代替整個同步方法;
2、盡量編寫不在同一時刻需要持有多個鎖的代碼,如果不可避免,則確保線程持有第二個鎖的時間盡量短暫;
3、創建和使用一個大鎖來代替若干小鎖,并把這個鎖用于互斥,而不是用作單個對象的對象級別鎖;
from:?http://www.importnew.com/20638.html
原文出處:?蘭亭風雨
總結
以上是生活随笔為你收集整理的Java并发编程(9):死锁(含代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java并发编程(8):多线程环境中安全
- 下一篇: Java编程入门(2.1):基础Java