JAVA语言之Java并发编程(9):死锁(含代码)
王红 2019-04-10 来源 : 阅读 97 评论 0

摘要:本文主要向大家介绍了JAVA语言之Java并发编程(9):死锁(含代码),通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言之Java并发编程(9):死锁(含代码),通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

JAVA语言之Java并发编程(9):死锁(含代码)

当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:

线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2。接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持有lock2,因此线程A会阻塞等待线程B对lock2的释放。如果此时线程B在持有lock2的时候,也在试图获取lock1,因为线程A正持有lock1,因此线程B会阻塞等待A对lock1的释放。二者都在等待对方所持有锁的释放,而二者却又都没释放自己所持有的锁,这时二者便会一直阻塞下去。这种情形称为死锁。

下面给出一个两个线程间产生死锁的示例,如下:

public class Deadlock extends Object {
private String objID;

public Deadlock(String id) {
objID = id;
}

public synchronized void checkOther(Deadlock other) {
print(""entering checkOther()"");
try { Thread.sleep(2000); }
catch ( InterruptedException x ) { }
print(""in checkOther() - about to "" + ""invoke 'other.action()'"");

//调用other对象的action方法,由于该方法是同步方法,因此会试图获取other对象的对象锁
other.action();
print(""leaving checkOther()"");
}

public synchronized void action() {
print(""entering action()"");
try { Thread.sleep(500); }
catch ( InterruptedException x ) { }
print(""leaving action()"");
}

public void print(String msg) {
threadPrint(""objID="" + objID + "" - "" + msg);
}

public static void threadPrint(String msg) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "": "" + msg);
}

public static void main(String[] args) {
final Deadlock obj1 = new Deadlock(""obj1"");
final Deadlock obj2 = new Deadlock(""obj2"");

Runnable runA = new Runnable() {
public void run() {
obj1.checkOther(obj2);
}
};

Thread threadA = new Thread(runA, ""threadA"");
threadA.start();

try { Thread.sleep(200); }
catch ( InterruptedException x ) { }

Runnable runB = new Runnable() {
public void run() {
obj2.checkOther(obj1);
}
};

Thread threadB = new Thread(runB, ""threadB"");
threadB.start();

try { Thread.sleep(5000); }
catch ( InterruptedException x ) { }

threadPrint(""finished sleeping"");

threadPrint(""about to interrupt() threadA"");
threadA.interrupt();

try { Thread.sleep(1000); }
catch ( InterruptedException x ) { }

threadPrint(""about to interrupt() threadB"");
threadB.interrupt();

try { Thread.sleep(1000); }
catch ( InterruptedException x ) { }

threadPrint(""did that break the deadlock?"");
}
}
运行结果如下:

从结果中可以看出,在执行到other.action()时,由于两个线程都在试图获取对方的锁,但对方都没有释放自己的锁,因而便产生了死锁,在主线程中试图中断两个线程,但都无果。

大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条件地发生,但即使是很小的概率,一旦发生,便可能造成毁灭性的破坏。避免死锁是一件困难的事,遵循以下原则有助于规避死锁:

1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;

2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;

3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

2年研发与教学经验

  • 10
    文章
  • 343
    人气
  • 0%
    受欢迎度

已有0人表明态度,0%喜欢该老师!

进入TA的空间
名师指导直通车
  • 资料索取
    资料索取
  • 答疑解惑
    答疑解惑
  • 技术交流
    技术交流
  • 职业测评
    职业测评
  • 面试技巧
    面试技巧
  • 高薪秘笈
    高薪秘笈
TA的其他文章 更多>>
JAVA语言之震惊,20年开发经验的技术总监不会搭建Java开发环境
职场感悟 100% 的用户喜欢
JAVA语言之Java 中不同的并行实现的性能比较
经验技巧 100% 的用户喜欢
JAVA语言之一次 HashSet 所引起的并发问题
经验技巧 0% 的用户喜欢
JAVA语言之Docker学习之搭建ActiveMQ消息服务
经验技巧 0% 的用户喜欢
JAVA语言之最基础的动态数据结构:链表
经验技巧 0% 的用户喜欢
其他海同名师 更多>>
刘新华
刘新华 联系TA
实力型。激情饱满,对专业充满热情
吴翠红
吴翠红 联系TA
独创“教、学、练、测”循环教学模式
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
黄泽民
黄泽民 联系TA
擅长javase核心技术
程钢
程钢 联系TA
擅长大型企业商业网站开发和管理
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

X
免费获取海同IT培训资料
验证码手机号,获得海同独家IT培训资料
获取验证码
提交

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    ICP许可  沪B2-20190160

站长统计