怎么防止死锁?如何避免死锁?
2 个回答
我疯狂地奔跑,只想为你承担一切的伤害,我竖起了山丘,不愿你看见我丑陋的脸庞。冰儿### 如何避免死锁 避免死锁的方法有多种,以下是一些常用的策略,其中之一是通过指定获取锁的顺序来避免死锁。下面详细介绍几种常见的避免死锁的方法: #### 1. **指定获取锁的顺序** 通过定义锁的获取顺序,可以避免多个线程在不同顺序上获取锁而导致的循环等待,从而避免死锁。例如: - **示例**:假设某个线程需要获得 A 锁和 B 锁才能对某资源进行操作。 - 规则:只有获得 A 锁的线程才有资格获取 B 锁,按顺序获取锁。 - **代码示例**: ```java public class AvoidDeadlock { private static final Object lockA = new Object(); private static final Object lockB = new Object(); public static void main(String[] args) { Thread thread1 = new Thread(() -> { synchronized (lockA) { System.out.println("Thread 1: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} synchronized (lockB) { System.out.println("Thread 1: Holding lock A & B..."); } } }); Thread thread2 = new Thread(() -> { synchronized (lockA) { // Notice the order is the same System.out.println("Thread 2: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} synchronized (lockB) { System.out.println("Thread 2: Holding lock A & B..."); } } }); thread1.start(); thread2.start(); } } ``` #### 2. **避免嵌套锁** 尽量减少嵌套锁的使用,即一个线程在持有一个锁的同时,尽量不要去请求另外一个锁。如果必须嵌套锁,可以尝试将相关代码重构,减少嵌套锁的深度。 #### 3. **使用 `tryLock`** 使用 `java.util.concurrent.locks.Lock` 的 `tryLock` 方法,可以尝试获取锁而不被阻塞。如果获取不到锁,可以选择适当的处理策略,而不是一直等待,从而避免死锁。 - **代码示例**: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class AvoidDeadlockWithTryLock { private static final Lock lockA = new ReentrantLock(); private static final Lock lockB = new ReentrantLock(); public static void main(String[] args) { Thread thread1 = new Thread(() -> { while (true) { try { if (lockA.tryLock()) { System.out.println("Thread 1: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} if (lockB.tryLock()) { try { System.out.println("Thread 1: Holding lock A & B..."); break; } finally { lockB.unlock(); } } lockA.unlock(); } } catch (Exception e) { e.printStackTrace(); } } }); Thread thread2 = new Thread(() -> { while (true) { try { if (lockA.tryLock()) { System.out.println("Thread 2: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} if (lockB.tryLock()) { try { System.out.println("Thread 2: Holding lock A & B..."); break; } finally { lockB.unlock(); } } lockA.unlock(); } } catch (Exception e) { e.printStackTrace(); } } }); thread1.start(); thread2.start(); } } ``` #### 4. **使用超时** 设置获取锁的超时时间,超过时间未获得锁,线程可以选择放弃获取锁或者进行其他处理,从而避免长时间等待造成的死锁。 - **代码示例**: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.TimeUnit; public class AvoidDeadlockWithTimeout { private static final Lock lockA = new ReentrantLock(); private static final Lock lockB = new ReentrantLock(); public static void main(String[] args) { Thread thread1 = new Thread(() -> { try { if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) { System.out.println("Thread 1: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) { try { System.out.println("Thread 1: Holding lock A & B..."); } finally { lockB.unlock(); } } lockA.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } }); Thread thread2 = new Thread(() -> { try { if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) { System.out.println("Thread 2: Holding lock A..."); try { Thread.sleep(50); } catch (InterruptedException e) {} if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) { try { System.out.println("Thread 2: Holding lock A & B..."); } finally { lockB.unlock(); } } lockA.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); } } ``` ### 总结 1. **指定获取锁的顺序**:通过定义锁的获取顺序,避免多个线程在不同顺序上获取锁而导致的循环等待。 2. **避免嵌套锁**:尽量减少嵌套锁的使用,降低死锁风险。 3. **使用 `tryLock`**:尝试获取锁而不阻塞,可以在获取不到锁时进行其他处理。 4. **使用超时**:设置获取锁的超时时间,超过时间未获得锁,线程可以放弃或进行其他处理。 通过以上方法,可以有效地避免死锁的发生,提高多线程程序的稳定性和性能。发布于 2023-07-27 19:44 •IP属地 上海举报评论收藏
见过花就好,何必在意花属于谁。java小生死锁的四个必要条件: 1. 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源 2. 3. 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放 4. 5. 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放 6. 7. 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系 这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。 理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。 所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算法,避免进程永久占据系统资源。 此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。发布于 2021-07-01 20:04 •IP属地 安徽举报评论收藏
公众号进入网站体验更佳

