Java中的无死锁同步

本文深入探讨了Java中死锁的起源、检测和预防方法,包括粗粒度和细粒度同步策略。通过锁定图分析潜在死锁,并通过一个银行模拟项目展示无死锁同步设计。强调在多线程编程中正确设计代码以消除死锁的重要性,同时提醒开发者注意隐藏的锁可能带来的死锁风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里,我们研究死锁的起源,考虑在现有代码中发现死锁的方法,并学习如何设计无死锁的同步。

线程同步是克服多线程程序中竞争条件的好工具。但是,它也有阴暗面。死锁:难以发现,重现和修复的令人讨厌的错误。防止它们发生的唯一可靠方法是正确设计您的代码,这是本文的主题。我们将研究死锁的起源,考虑在现有代码中发现潜在死锁的方法,并介绍设计无死锁同步的实用方法。这些概念将通过一个简单的演示项目进行说明。

假定读者已经熟悉多线程编程,并且对Java中的线程同步原语有很好的理解。在以下各节中,我们将不会在同步语句和锁API之间进行区分,而是将术语“锁”用于两种类型的可重入锁,在示例中更喜欢前者。

1.死锁机制

让我们回顾一下僵局的工作方式。请考虑以下两种方法:在这里插入图片描述
这些方法是有意设计的,以产生死锁。让我们详细考虑这是如何发生的。

两个增量()和减量()基本上由以下5个步骤:在这里插入图片描述
显然,只有相应的锁是空闲的,两种方法中的步骤1和2才可以通过,否则,执行线程将不得不等待它们的释放。

假设有两个并行线程,一个执行增量(),另一个执行减量()。每个线程的步骤将以正常顺序执行,但是,如果我们将两个线程放在一起考虑,则一个线程的步骤将与另一个线程的步骤随机交织。随机性来自系统线程调度程序施加的不可预测的延迟。可能的交织模式或场景非常多(准确地说,有252种),并且可以分为两组。第一组是其中一个线程足够快地获取两个锁的位置在这里插入图片描述
该组中的所有情况均导致成功完成。

在第二组中,两个线程均成功获取锁。在这里插入图片描述
该组中的所有情况都会导致第一个线程等待第二个线程拥有的锁,而第二个线程等待第一个线程拥有的锁,因此两个线程无法继续进行下去:
在这里插入图片描述
这是典型的死锁情况,具有所有典型特性。让我们概述重要的:

  • 至少有两个线程,每个线程至少具有两个锁。
  • 死锁仅在线程定时的特定组合时发生。
  • 死锁的发生取决于锁定顺序。
    第二个属性意味着无法随意复制死锁。此外,它们的可重复性取决于操作系统,CPU频率,CPU负载和其他因素。后者意味着软件测试的概念仅适用于死锁,因为同一代码在一个系统上可能完
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值