`
20386053
  • 浏览: 433521 次
文章分类
社区版块
存档分类
最新评论

Java并发编程学习笔记之九:死锁(含代码)

 
阅读更多

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200937


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

线程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并发编程:设计原则与模式(第二版)

    java并发方面的两大名著之一。读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法...贯串全书的大量示例代码详细地阐述了在讨论中所涉及到的并发编程理念的细微之处。

    java并发编程

    本书全面介绍了如何使用Java 2平台进行并发编程,较上一版新增和扩展的内容包括:, ·存储模型 ·取消 ·可移植的并行编程 ·实现...贯串全书的大量示例代码详细地阐述了在讨论中所涉及到的并发编程理念的细微之处。

    Java并发编程(学习笔记).xmind

    Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...

    龙果 java并发编程原理实战

    第4节学习并发的四个阶段并推荐学习并发的资料 [免费观看] 00:09:13分钟 | 第5节线程的状态以及各状态之间的转换详解00:21:56分钟 | 第6节线程的初始化,中断以及其源码讲解00:21:26分钟 | 第7节多种创建线程的...

    实验二:死锁的检测和预防.doc

    实验二:死锁的检测和预防.doc

    java并发编程教程源码

    并发编程简介 将串行执行部分编程并发执行,但要考虑上下文切换和资源调度的时间 并发编程的意义及影响多线程的因素 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发...

    java并发编程:juc线程池

    在当今计算机软件开发领域,多核处理器的广泛应用使得并发编程成为开发者必备的技能之一。而了解 Java 并发编程以及其中的 JUC(java.util.concurrent)线程池,对于构建高性能、高可伸缩性的应用程序具有重要意义。...

    java并发编程艺术

    java学习的利器;并发编程的目的是为了让程序运行的更快,但是并不是启动更多的线程,就能让程序最大限度的并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行的更快,会面临非常多的挑战,比如上...

    java 并发编程教程

    java 并发编程 ThreadLocal 内存模型 JDK并发包编程 并发集合 显示锁 数据冲突 死锁

    龙果java并发编程完整视频

    第4节学习并发的四个阶段并推荐学习并发的资料 [免费观看] 00:09:13分钟 | 第5节线程的状态以及各状态之间的转换详解00:21:56分钟 | 第6节线程的初始化,中断以及其源码讲解00:21:26分钟 | 第7节多种创建线程的...

    Java 并发编程原理与实战视频

    第4节学习并发的四个阶段并推荐学习并发的资料 [免费观看] 00:09:13分钟 | 第5节线程的状态以及各状态之间的转换详解00:21:56分钟 | 第6节线程的初始化,中断以及其源码讲解00:21:26分钟 | 第7节多种创建线程的...

    Java 死锁示例性源代码

    本源代码是博客《Java 多线程编程之七:死锁(附源代码)》附带的实例性源代码。原博客链接地址:http://blog.csdn.net/defonds/archive/2010/01/26/5258120.aspx。

    java并发编程理论基础精讲

    本资源为您提供了关于 Java 并发编程理论基础的精讲,涵盖了多线程编程的核心概念、基本原理以及在 Java 中的应用。通过深入学习,您将建立坚实的并发编程基础,能够更好地理解和应对多线程编程中的挑战。 并发编程...

    Java并发编程原理与实战

    理解自旋锁,死锁与重入锁.mp4 深入理解volatile原理与使用.mp4 JDK5提供的原子类的操作以及实现原理.mp4 Lock接口认识与使用.mp4 手动实现一个可重入锁.mp4 AbstractQueuedSynchronizer(AQS)详解.mp4 使用AQS重写...

    java死锁源码java死锁源码

    java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁...

    Java并发编程实战

    Java并发编程实战 本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及...

    java 并发学习总结

    java并发学习总结 例子:包含(并发容器、同步容器、同步工具、死锁、异常、中断、线程池、返回结果、同步方法等代码例子)

    java并发编程面试题

    java并发编程 基础知识,守护线程与线程, 并行和并发有什么区别? 什么是上下文切换? 线程和进程区别 什么是线程和进程? 创建线程有哪几种方式?,如何避免线程死锁 线程的 run()和 start()有什么区别? 什么是 ...

    操作系统:死锁实验报告

    操作系统实验报告:死锁 银行家算法源代码和运行结果的截图。

Global site tag (gtag.js) - Google Analytics