JAVA 100道题(25)

25.实现一个死锁示例,并解释如何避免死锁。

在Java中,死锁通常发生在两个或更多的线程无限期地等待一个资源,而该资源又被另一个线程持有,后者也在等待另一个线程释放资源。这形成了一个循环等待条件,导致所有涉及的线程都无法继续执行。

下面是一个简单的Java死锁示例:

复制代码

java复制代码

|---|----------------------------------------------------------------------------------------------|
| | public class DeadlockExample { |
| | private final Object lock1 = new Object(); |
| | private final Object lock2 = new Object(); |
| | |
| | public void method1() { |
| | synchronized (lock1) { |
| | System.out.println("Thread " + Thread.currentThread().getId() + " acquired lock1"); |
| | try { |
| | Thread.sleep(100); |
| | } catch (InterruptedException e) { |
| | e.printStackTrace(); |
| | } |
| | System.out.println("Thread " + Thread.currentThread().getId() + " is waiting for lock2"); |
| | synchronized (lock2) { |
| | System.out.println("Thread " + Thread.currentThread().getId() + " acquired lock2"); |
| | } |
| | } |
| | } |
| | |
| | public void method2() { |
| | synchronized (lock2) { |
| | System.out.println("Thread " + Thread.currentThread().getId() + " acquired lock2"); |
| | try { |
| | Thread.sleep(100); |
| | } catch (InterruptedException e) { |
| | e.printStackTrace(); |
| | } |
| | System.out.println("Thread " + Thread.currentThread().getId() + " is waiting for lock1"); |
| | synchronized (lock1) { |
| | System.out.println("Thread " + Thread.currentThread().getId() + " acquired lock1"); |
| | } |
| | } |
| | } |
| | |
| | public static void main(String[] args) { |
| | DeadlockExample deadlockExample = new DeadlockExample(); |
| | |
| | Thread thread1 = new Thread(() -> deadlockExample.method1()); |
| | Thread thread2 = new Thread(() -> deadlockExample.method2()); |
| | |
| | thread1.start(); |
| | thread2.start(); |
| | } |
| | } |

在这个示例中,method1method2 分别持有 lock1lock2,并试图获取另一个锁。如果两个线程几乎同时执行,它们可能会各自持有一个锁并等待另一个锁,从而导致死锁。

要避免死锁,可以遵循以下策略:

  1. 避免嵌套锁:尽量不要在一个线程中嵌套获取多个锁。如果必须这样做,确保以一致的顺序获取锁。
  2. 设置锁超时:为锁操作设置超时,如果线程在指定的时间内无法获取锁,则放弃并稍后重试。
  3. 使用锁顺序:如果多个线程需要访问多个资源,确保它们总是以相同的顺序请求锁。这可以防止循环等待条件。
  4. 检测死锁:使用工具或算法来检测死锁,并在检测到死锁时采取适当的措施,如回滚事务或释放资源。
  5. 使用高级并发工具 :Java提供了许多高级的并发工具,如SemaphoreCountDownLatchCyclicBarrier等,它们有助于更安全、更有效地管理并发操作。
  6. 减少锁的粒度:尽量减小锁的粒度,只锁定必要的资源或代码段,以减少线程之间的冲突。

记住,避免死锁需要仔细规划和管理并发代码。在设计并发系统时,始终考虑可能发生的竞争条件和死锁场景,并采取相应的预防措施。

相关推荐
budingxiaomoli几秒前
多线程(一)
java·开发语言·jvm·java-ee
今天没有盐9 分钟前
Pandas缺失值处理完全指南:从基础操作到高级技巧
python·pycharm·编程语言
程序员小远19 分钟前
快速定位bug,编写测试用例
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·bug
Yue丶越20 分钟前
【C语言】深入理解指针(二)
c语言·开发语言·数据结构·算法·排序算法
B站_计算机毕业设计之家24 分钟前
大数据YOLOv8无人机目标检测跟踪识别系统 深度学习 PySide界面设计 大数据 ✅
大数据·python·深度学习·信息可视化·数据挖掘·数据分析·flask
m0_7482480225 分钟前
C++中的位运算符:与、或、异或详解
java·c++·算法
介一安全25 分钟前
从 0 到 1 玩转 2025 最新 WebGoat 靶场:环境搭建 + 全关卡漏洞解析(超级详细)
java·web安全·网络安全·靶场
web安全工具库25 分钟前
Linux进程的:深入理解子进程回收与僵尸进程
java·linux·数据库
沐浴露z26 分钟前
详解【限流算法】:令牌桶、漏桶、计算器算法及Java实现
java·算法·限流算法
老歌老听老掉牙42 分钟前
解决 PyQt5 中 sipPyTypeDict() 弃用警告的完整指南
python·qt