JavaJava关于死锁产生条件以及死锁示例
inkOrCloud死锁产生条件
死锁产生有四大必要条件,只要不满足其中一种即可避免死锁
- 互斥条件: 资源是独占的,一次只能被一个线程使用。
- 请求与保持条件: 线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源被其他线程占有。
- 不剥夺条件: 线程已获得的资源在未使用完之前,不能被强行剥夺。
- 循环等待条件: 若干线程之间形成一种头尾相接的循环等待资源关系。(例如线程A持有资源1,需要资源2;线程B持有资源2,需要资源3;线程C持有资源3,需要资源1)
几种常见死锁示例
嵌套锁死锁
嵌套锁死锁在一个线程试图以不同顺序获取多个锁可能发生,例如:
- 线程A获取锁1,然后尝试获取锁2
- 线程B获取锁2,然后尝试获取锁1
示例代码
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
| public class NestedLockDeadlock { private static final Object lock1 = new Object(); private static final Object lock2 = new Object();
public static void main(String[] args) { Thread thread1 = new Thread(() -> { synchronized (lock1) { System.out.println("Thread 1: 持有 lock1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread 1: 等待 lock2"); synchronized (lock2) { System.out.println("Thread 1: 持有 lock1 和 lock2"); } } });
Thread thread2 = new Thread(() -> { synchronized (lock2) { System.out.println("Thread 2: 持有 lock2"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread 2: 等待 lock1"); synchronized (lock1) { System.out.println("Thread 2: 持有 lock2 和 lock1"); } } });
thread1.start(); thread2.start(); } }
|
资源锁死锁
最常见的死锁,在线程竞争有限资源时会发生
示例代码:
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
| public class ResourceDeadlock { public static void main(String[] args) { Object resource1 = new Object(); Object resource2 = new Object();
Thread t1 = new Thread(() -> { synchronized (resource1) { System.out.println("线程1获取到resource1"); try { Thread.sleep(500); } catch (InterruptedException e) { System.out.println("线程等待异常"); } synchronized (resource2) { System.out.println("线程1获取到resource2"); } } });
Thread t2 = new Thread(() -> { synchronized (resource2) { System.out.println("线程2获取到resource2"); try { Thread.sleep(500); } catch (InterruptedException e) { System.out.println("线程等待异常"); } synchronized (resource1) { System.out.println("线程2获取到resource1"); } } }); t1.start(); t2.start(); } }
|
哲学家就餐问题
多个哲学家(线程)共享有限的餐具(资源),可能导致所有哲学家都在等待其他人放下餐具的情况。哲学家就餐问题可以视为已从特殊的资源锁死锁。
示例代码:
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
| import java.util.*;
public class Main { public static void main(String[] args) throws InterruptedException{ Philosopher philosopher1 = new Philosopher(0); Philosopher philosopher2 = new Philosopher(1); Philosopher philosopher3 = new Philosopher(2); Philosopher philosopher4 = new Philosopher(3); Table table = new Table(4); philosopher1.repeat(table); philosopher2.repeat(table); philosopher3.repeat(table); philosopher4.repeat(table); } }
class Table { ArrayList<Object> chopsticks = new ArrayList<>(); public Table(int n) { for (int i = 0; i < n; i++) { this.chopsticks.add(new Object()); } } }
class Philosopher { int num; public void repeat(Table table){ Thread t1 = new Thread() { @Override public void run(){ synchronized (table.chopsticks.get(num)) { System.out.println("哲学家"+num+"拿起左手筷子"); try { Thread.sleep(3000); }catch (InterruptedException e) { System.out.println("线程等待异常"); return; } if (num == table.chopsticks.size() - 1) { synchronized (table.chopsticks.get(0)) { System.out.println("哲学家"+num+"拿起右手筷子"); } }else { synchronized (table.chopsticks.get(num + 1)) { System.out.println("哲学家"+num+"拿起右手筷子"); } } } } }; t1.start(); } public Philosopher(int n) { this.num = n; } }
|