Java面试问题,如何避免Java线程中的死锁?

如何避免Java中的死锁?是流行的Java面试问题之一,也是多线程的流行话题之一。尽管问题看起来很简单,但是一旦深入,大多数Java开发人员就会陷入困境。

面试问题以“什么是死锁?”当两个或多个线程正在等待彼此释放所需资源(锁定)并陷入无限时间的阻塞时,这种情况称为死锁,它只会在多任务或多线程的情况下发生。

如何检测Java中的死锁?

虽然这可能有很多答案,但我的版本是,如果我看到嵌套的同步块,或者从其他同步方法调用一个同步方法,或者试图在不同的对象上获得锁,那么如果开发人员不是非常小心,就很可能出现死锁。

另一种方法是在运行应用程序时发现线程被锁定,尝试使用线程转储,在Linux中可以通过命令“kill -3”来实现,这将打印应用程序日志文件中所有线程的状态,就可以看到哪个线程被锁定在哪个对象上。

也可以使用fastthread等工具分析线程转储,上传你的线程转储并分析它。

另一种方法是使用jConsole/VisualVM,它将准确地显示哪些线程被锁定,以及在哪个对象上。

编写一个会导致死锁的Java程序

一旦回答了前面的问题,他们可能会要求你编写导致Java死锁的代码

这是我的一个版本

/**

* Java程序通过强制循环等待来创建死锁

*

* @author WINDOWS 8

*

*/

public class DeadLockDemo {

/*

* T此方法请求两个锁,首先是String,然后是Integer

*/

public void method1() {

synchronized (String.class) {

System.out.println("Aquired lock onString.classobject");

synchronized (Integer.class) {

System.out.println("Aquired lock on Integer.class object");

}

}

}

/* * 此方法也请求相同的两个锁

* 顺序相反,先整型,然后是字符串

* 如果一个线程持有字符串锁,则会产生潜在的死锁

* 另一个持有整数锁,它们会一直等待对方

*/

public void method2() {

synchronized (Integer.class) {

System.out.println("Aquired lock on Integer.classobject");

synchronized (String.class) {

System.out.println("Aquired lock on String.class object");

}

}

}

}

如果method1()和method2()都将被两个或多个线程调用,那么死锁的可能性很大,如果线程1在执行method1()时获取Sting对象上的锁,而线程2在执行method2()时获取Integer对象上的锁,那么线程2将等待对方释放Integer和String上的锁以继续执行,而这永远不会发生

此图准确演示了我们的程序,其中一个线程持有一个对象的锁并等待其他线程持有的其他对象锁。

这个图展示了我们的这个程序,一个线程持有一个对象的锁,等待另一个线程持有的其他对象锁。

你可以看到线程1想要对线程2持有的对象2的锁定,而线程2想要对线程1持有的对象1进行锁定。由于没有线程愿意放弃,所以存在死锁并且Java程序卡住了。

如何避免Java中的死锁

现在面试官来到最后一部分,这是我认为最重要的部分之一; 你如何修复代码中的死锁?或者如何避免Java中的死锁?

如果仔细查看了上面的代码,那么你可能已经发现死锁的真正原因不是多线程,而是它们请求锁定的方式,如果提供有序访问,则问题将得到解决。

这是我的固定版本,它避免了由于没有抢占无效循环等待导致的死锁,这是需要死锁的四个条件之一。

public class DeadLockFixed {

/**

* 两种方法现在都以相同的顺序请求锁定,首先是Integer,然后是String。

* 也可以完成反向,例如第一个String然后是Integer

* 两者都会解决问题,只要两种方法都请求锁定

* 按照一致的顺序

*/

public void method1() {

synchronized (Integer.class) {

System.out.println("Aquired lock on Integer.class object");

synchronized (String.class) {

System.out.println("Aquired lock on String.class object");

}

}

}

public void method2() {

synchronized (Integer.class) {

System.out.println("Aquired lock on Integer.class object");

synchronized (String.class) {

System.out.println("Aquired lock on String.class object");

}

}

}

}

现在不存在任何死锁,因为两个方法都以相同的顺序访问Integer和String类文字的锁。因此,如果线程A获取对Integer对象的锁定,则线程B将不会继续,直到线程A释放整数锁定,同样,即使线程B保持字符串锁定,线程A也不会被阻止,因为现在线程B不会期望线程A释放整数锁定继续进行。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358

推荐阅读更多精彩内容