如何在编写并发程序时避免死锁

如何在编写并发程序时避免死锁 -Java示例

Java中的多线程和并行计算

大家好,您是否想学习在编写并发程序时如何避免死锁,尤其是在Java中? 编写正确的并发应用程序绝非易事,因为您必须处理多个并发问题,例如竞态条件 ,活动锁, 死锁 ,内存干扰等。

在本文中,我将告诉您如何在编写并发程序作为面试问题讨论时避免死锁。 由于我是Java开发人员,因此我将解释Java的概念和实现,但是我将与您分享的技术适用于所有编程语言,例如C ++或C#等。

避免死锁的问题是流行的Java面试问题之一 ,多线程主要是在高层面试中提出的,其中涉及许多后续问题。

尽管这个问题看起来很基础,但是一旦您开始深入研究,大多数Java开发人员就会陷入困境。

那么, 什么是僵局? 答案很简单-当两个或多个线程彼此等待释放所需的资源(锁定)并无限期陷入困境时,这种情况称为死锁。

它只会在多任务 或多线程的情况下发生,因为这是多线程进入的地方。

1.如何在Java中检测死锁?

尽管这可能会有很多答案,但首先,我将查看代码以查看嵌套的同步块是否正在从另一个调用同步方法 ,或者是否正在尝试锁定另一个对象。

如果是这样,如果开发人员不小心,则很有可能发生死锁。

确定死锁风险的另一种方法是在运行应用程序时实际上陷入僵局。

如果发生这种情况,请尝试进行线程转储 ,在Linux中,您可以通过命令“ kill -3”来执行此操作 这将在应用程序日志文件中打印所有线程的状态,您可以看到哪个线程被锁定在哪个对象上。

您可以使用fastthread.io之类的工具来分析该线程转储,该工具允许您上载线程转储并进行分析。

另一种方法是使用jConsole / VisualVM 。 它将准确显示锁定的线程和对象。

如果您对学习故障排除工具和分析线程转储的过程感兴趣,建议您看一下Uriah Levy在Pluralsight上的“ 分析Java线程转储”课程。

这是一门高级实践课程,旨在学习有关Java线程转储的更多信息,并使您熟悉其他流行的高级故障排除工具。

分析Java线程转储

顺便说一句,您需要具有Pluralsight会员身份才能访问此课程,该课程每月费用约为$ 29或每年$ 299 (折扣14%)。

如果您没有Pluralsight会员资格 ,建议您参加其中,因为它使您可以访问其5000多种在线课程,这些课程涉及前端和后端开发,机器学习等所有最新主题。

它还包括交互式测验,练习和最新的认证材料。
它更像是面向软件开发人员的Netflix,并且由于学习是我们工作的重要组成部分,因此Plurlasight会员资格是保持竞争优势的绝佳方法。

他们还提供了10天的免费试用,没有任何承诺,这是一种绝佳的方式,不仅可以免费访问此课程,而且可以在加入Pluralsight之前检查课程的质量。

2.编写将导致死锁的Java程序

一旦回答了前面的问题,他们可能会问您如何编写代码,从而导致Java陷入僵局。

这是一种实现方法:

Java中的多线程和并行计算

如果method1()和method2()都被两个或多个线程调用,则很有可能发生死锁 ,因为如果线程1在执行method1()时获取了String对象的锁,而线程2则获取了Integer的锁,在执行method2()的对象时, 两者都将彼此等待以释放对Integer 的锁定 ,并且String继续进行下去,这将永远无法进行。

该图有效地演示了我们的程序,其中一个线程在一个对象上持有一个锁,并在等待另一对象持有的另一对象被锁定。

将并发和多线程应用于常见的Java模式

您可以看到线程1希望锁定对象2,该对象由线程2持有,线程2希望锁定对象1,该对象1由线程1持有。

由于没有线程愿意放弃,因此存在死锁,并且Java程序被卡住了。 这种情况也称为“没有抢占的循环等待”。

这个想法是您应该知道使用常见并发模式的正确方法,如果您不熟悉它们,那么Jose Paumard撰写的将并发和多线程应用于Common Java Patterns是学习的好起点。

3.如何避免Java中的死锁

现在,面试官进入最后一部分,这是我认为最重要的问题之一: 如何解决代码的僵局?

如果仔细查看了上面的代码,那么您可能已经发现造成死锁的真正原因不是多个线程,而是它们请求锁定的方式。

如果您提供 有序访问权限 ,则问题将得到解决。

这是我的固定版本,它通过使用没有抢占循环等待来避免死锁。 这是死锁所需的四个条件之一

Heinz Kabutz的Java Concurrency in Practice Bundle

现在,将不会有任何死锁,因为这两个方法都以相同的顺序访问Integer和String类文字的锁。

因此,如果线程A获得了对Integer对象的锁定,则直到线程A释放Integer锁定后,线程B才会继续进行。

即使线程B持有String锁,也以不会阻塞线程A的相同方式完成此操作,因为现在,线程B将不希望线程A释放整数锁以继续进行任何操作。

这就是如何在编写并发程序时避免死锁 。 正如我已经说过的,即使是Java中的讨论和示例,我共享的技术,有序访问共享资源的方法也是独立于语言的,并且适用于所有地方。

正式地,这被称为打破死锁所需的无等待的循环等待条件,但我只是称其为共享资源的有序访问。

如果您想大致了解有关并发,多线程和并发编程的更多信息,请参考以下有用的资源:

进阶学习

Java中的多线程和并行计算
实践中的Java并发性-本书
将并发和多线程应用于常见的Java模式
Heinz Kabutz的Java Concurrency in Practice Bundle
10个Java多线程和并发最佳实践
Java中的前50个多线程和并发问题

结束语

感谢您到目前为止阅读本文。 您可能会认为这很简单,但是我告诉您,这是一个重要的概念,对于编写正确的并发程序以及在面试中表现出色都很重要。

归根结底,您应该对这里提到的事情有足够的知识和经验。

并发编程之旅祝您好运! 当然这并非易事 ,但是通过遵循此路线图和指南,您离成为更好的开发人员仅一步之遥 ,而您一直想成为

如果您喜欢这篇文章,请考虑关注我( javinpaul )。 如果您想收到每条新帖子的通知,并且不要忘记关注 在Twitter上再次访问java

PS —如果您想学习Java和Multithreading并寻找一些免费课程,请查看J ava Multithreading —一门#FREE课程

From: https://hackernoon.com/how-to-avoid-a-deadlock-while-writing-concurrent-programs-java-example-988bb07db25f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值