循环死锁

描述

哲学家聚餐问题是并发编程中的经典计算机科学问题。哲学家聚餐问题将导致循环死锁问题。循环死锁是死锁问题的一种变体。发生死锁之后,恢复的唯一方法是重新启动 JVM。

请参考上图。您可以看到:

  • “Thread-0”持有锁 L1 并在等待锁 L2。
  • “Thread-1”持有锁 L2 并在等待锁 L3。
  • “Thread-2”持有锁 L3 并在等待锁 L4。
  • “Thread-3”持有锁 L4 并在等待锁 L1。

由于每个线程都持有一个锁,其他线程正好也在等待这个锁,这最终就导致了循环死锁。此时就需要对代码进行重新设计以打破这种循环死锁模式。

示例

下方是一个取自哲学家聚餐问题程序 JVM 实例的线程转储文件,其中显示了循环死锁问题的一些信息。

"Thread-4" prio=6 tid=0x0000000007466800 nid=0x158f5c waiting on condition [0x0000000008fcf000]
java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  0x00000007ac3b2718 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
	at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
	at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
	at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
	- 0x00000007ac3b27d8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Thread-3" prio=6 tid=0x0000000007465800 nid=0x158f58 waiting on condition [0x0000000008e0f000]
java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  0x00000007ac3b27d8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
	at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
	at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
	at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
	- 0x00000007ac3b27a8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Thread-2" prio=6 tid=0x0000000007465000 nid=0x158f54 waiting on condition [0x000000000895e000]
java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  0x00000007ac3b27a8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
	at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
	at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
	at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
	- 0x00000007ac3b2778 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Thread-1" prio=6 tid=0x0000000007462000 nid=0x158f50 waiting on condition [0x0000000008cce000]
java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  0x00000007ac3b2778 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
	at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
	at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
	at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
	- 0x00000007ac3b2748 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Thread-0" prio=6 tid=0x0000000007461800 nid=0x158f4c waiting on condition [0x0000000008ace000]
java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  0x00000007ac3b2748 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
	at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
	at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
	at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
	- 0x00000007ac3b2718 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

从以上转储文件中,我们可以看到

  • “Thread-4”正在等待由“Thread-0”持有的 0x00000007ac3b2718
  • “Thread-0”正在等待由“Thread-1”持有的 0x00000007ac3b2748
  • “Thread-1”正在等待由“Thread-2”持有的 0x00000007ac3b2778
  • “Thread-2”正在等待由“Thread-3”持有的 0x00000007ac3b27a8
  • “Thread-3”正在等待由“Thread-4”持有的 0x00000007ac3b27d8

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: