併發死鎖示例

初始

死鎖是指兩個或者兩個以上的線程在執行過程中,因爭奪資源而造成的互相等待的現象,在無外力作用的情況下,這些線程會一直相互等待而無法繼續運行下去。

如圖:
在這裏插入圖片描述

  1. 線程A已經持有了資源2,他同時還想申請資源1
  2. 線程B已經持有了資源1,它同時還想申請資源2

所以兩個線程相互等待對方已經持有的資源而進入了死鎖狀態。

死鎖產生並備的四個條件

  • 互斥條件

    指線程對已經獲取到的資源進行排它性使用,即該資源同時只由一個線程佔用。

  • 請求並持有條件

    指一個線程已經持有了一個資源,但又提出了新的資源請求,而新資源已被其他線程佔用,所有當前線程會被阻塞,但阻塞的同時並不釋放自己已經獲取的資源。

  • 不可剝奪條件

    指線程獲取到的資源在自己使用完之前不能被其他線程搶佔,只有在自己使用完畢之後才由自己釋放該資源。

  • 環路等待條件

    指在發生死鎖時,必然存在一個線程一資源的環形鏈,即線程1等線程2佔用的資源,線程2等線程3佔用的資源,…線程n等待線程1佔用的資源。

代碼示例

public class DeadLockDemo {
	private static Object resourceA = new Object();
	private static Object resourceB = new Object();

	public static void main(String[] args) {
		new Thread(() -> {
			synchronized (resourceA) {
				System.out.println(Thread.currentThread() + "get resourceA");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread() + "waiting get resourceB");
				synchronized (resourceB) {
					System.out.println(Thread.currentThread() + "get resourceB");
				}
			}
		}).start();

		new Thread(() -> {
			synchronized (resourceB) {
				System.out.println(Thread.currentThread() + "get resourceB");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread() + "waiting get resourceA");
				synchronized (resourceA) {
					System.out.println(Thread.currentThread() + "get resourceA");
				}
			}
		}).start();
	}
}

/*返回
Thread[Thread-0,5,main]get resourceA
Thread[Thread-1,5,main]get resourceB
Thread[Thread-1,5,main]waiting get resourceA
Thread[Thread-0,5,main]waiting get resourceB
*/

查看死鎖進程

>jps
38324 DeadLockDemo
>jstack 38324
"Thread-1" #10 prio=5 os_prio=0 tid=0x15472000 nid=0x35e0 waiting for monitor entry [0x1581f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.syq.demo.concurrent.DeadLockDemo.lambda$main$1(DeadLockDemo.java:39)
        - waiting to lock <0x04d0bd68> (a java.lang.Object)
        - locked <0x04d0bd70> (a java.lang.Object)
        at com.syq.demo.concurrent.DeadLockDemo$$Lambda$2/19993396.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

"Thread-0" #9 prio=5 os_prio=0 tid=0x15471c00 nid=0x92c waiting for monitor entry [0x1578f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.syq.demo.concurrent.DeadLockDemo.lambda$main$0(DeadLockDemo.java:24)
        - waiting to lock <0x04d0bd70> (a java.lang.Object)
        - locked <0x04d0bd68> (a java.lang.Object)
        at com.syq.demo.concurrent.DeadLockDemo$$Lambda$1/17290025.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

避免死鎖

避免死鎖,只需要破壞掉至少一個必要條件即可。

只有請求並持有條件和環路等待條件是可以破壞的。

我們可以讓資源有序性,即每個線程都是先得到資源1在去拿資源2。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章