发生死锁的原因通常是两个对象的锁相互等待造成的。

以下用一个实例来构造这样的情况:

package basic.e_deadlock;

import org.apache.log4j.Logger;

public class TestDeadLock {
public static void main(String[] args) {
DeadlockRisk dead = new DeadlockRisk();
MyThread t1 = new MyThread(dead, 1, 2, "线程1");
MyThread t2 = new MyThread(dead, 3, 4, "线程2");
MyThread t3 = new MyThread(dead, 5, 6, "线程3");
MyThread t4 = new MyThread(dead, 7, 8, "线程4");
t1.start();
t2.start();
t3.start();
t4.start();
}
} class MyThread extends Thread {
private DeadlockRisk dead;
private int a, b; MyThread(DeadlockRisk dead, int a, int b, String threadName) {
this.dead = dead;
this.a = a;
this.b = b;
this.setName(threadName);
} @Override
public void run() {
dead.read();
dead.write(a, b);
}
} class DeadlockRisk {
private static Logger logger = Logger.getLogger(DeadlockRisk.class);
private static class Resource {
public int value;
} private Resource resourceA = new Resource();
private Resource resourceB = new Resource(); public void read() {
logger.debug("===========read begin===========");
synchronized (resourceA) {
logger.debug("read():" + Thread.currentThread().getName() + "获取了resourceA 的锁!");
synchronized (resourceB) {
logger.debug("read():" + Thread.currentThread().getName() + "获取了resourceB 的锁!");
}
}
logger.debug("===========read end=============");
} public void write(int a, int b) {
logger.debug("===========write begin===========");
synchronized (resourceB) {
logger.debug("write():" + Thread.currentThread().getName() + "获取了resourceB 的锁!");
synchronized (resourceA) {
logger.debug("write():" + Thread.currentThread().getName() + "获取了resourceA 的锁!");
resourceA.value = a;
resourceB.value = b;
}
}
logger.debug("===========write end=============");
}
}

运行结果:

0    [线程1] DEBUG basic.e_deadlock.DeadlockRisk - ===========read  begin===========
0 [线程2] DEBUG basic.e_deadlock.DeadlockRisk - ===========read begin===========
0 [线程4] DEBUG basic.e_deadlock.DeadlockRisk - ===========read begin===========
0 [线程3] DEBUG basic.e_deadlock.DeadlockRisk - ===========read begin===========
0 [线程1] DEBUG basic.e_deadlock.DeadlockRisk - read():线程1获取了resourceA 的锁!
0 [线程1] DEBUG basic.e_deadlock.DeadlockRisk - read():线程1获取了resourceB 的锁!
0 [线程1] DEBUG basic.e_deadlock.DeadlockRisk - ===========read end=============
0 [线程2] DEBUG basic.e_deadlock.DeadlockRisk - read():线程2获取了resourceA 的锁!
0 [线程1] DEBUG basic.e_deadlock.DeadlockRisk - ===========write being===========
1 [线程2] DEBUG basic.e_deadlock.DeadlockRisk - read():线程2获取了resourceB 的锁!
1 [线程2] DEBUG basic.e_deadlock.DeadlockRisk - ===========read end=============
1 [线程2] DEBUG basic.e_deadlock.DeadlockRisk - ===========write being===========
1 [线程1] DEBUG basic.e_deadlock.DeadlockRisk - write():线程1获取了resourceB 的锁!
1 [线程4] DEBUG basic.e_deadlock.DeadlockRisk - read():线程4获取了resourceA 的锁!

注意:此时线程1在等待resourceB的资源,线程2在等待resourceA的资源。两个线程在相互等待,出现死锁。

Java多线程:线程死锁的更多相关文章

  1. Java多线程——线程的死锁

    Java多线程——线程的死锁 摘要:本文主要介绍了Java多线程中遇到的死锁问题. 部分内容来自以下博客: https://www.cnblogs.com/wy697495/p/9757982.htm ...

  2. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  3. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  4. Java多线程--线程及相关的Java API

    Java多线程--线程及相关的Java API 线程与进程 进程是线程的容器,程序是指令.数据的组织形式,进程是程序的实体. 一个进程中可以容纳若干个线程,线程是轻量级的进程,是程序执行的最小单位.我 ...

  5. Java多线程-线程的同步(同步方法)

    线程的同步是保证多线程安全访问竞争资源的一种手段.线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源.什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些 ...

  6. Java多线程——线程的优先级和生命周期

    Java多线程——线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...

  7. Java多线程——线程的创建方式

    Java多线程——线程的创建方式 摘要:本文主要学习了线程的创建方式,线程的常用属性和方法,以及线程的几个基本状态. 部分内容来自以下博客: https://www.cnblogs.com/dolph ...

  8. Java多线程——线程之间的协作

    Java多线程——线程之间的协作 摘要:本文主要学习多线程之间是如何协作的,以及如何使用wait()方法与notify()/notifyAll()方法. 部分内容来自以下博客: https://www ...

  9. Java多线程——线程之间的同步

    Java多线程——线程之间的同步 摘要:本文主要学习多线程之间是如何同步的,如何使用volatile关键字,如何使用synchronized修饰的同步代码块和同步方法解决线程安全问题. 部分内容来自以 ...

随机推荐

  1. python中隐式的内存共享

    在python中,基本上使用的是引用,那么就会造成一个隐式的内存共享,特别是在容器对象中,例如list,dictionary 对于不可变对象,是不会造成隐式的内存共享情况,如下所示: >> ...

  2. nagios-解决监控页面上的乱码

    1. 前景 在nagios的监控页面上发现返回来的信息为乱码,如下图所示: 查看相关日志,发现正常显示汉字,如下: 2. 解决方法(以下两个步骤缺一不可) 主要原因分析如下: 在nagios服务器上发 ...

  3. MySQL安装(图文详解)

    下面的是MySQL安装的图解,用的可执行文件安装的,详细说明了一下!打开下载的mysql安装文件mysql-5.0.27-win32.zip,双击解压缩,运行“setup.exe”,出现如下界面 my ...

  4. (转载)OC学习篇之---Foundation框架中的NSString对象和NSMutableString对象

    在之前的一篇文章中我们说到了Foundation框架中的NSObject对象,那么今天在在来继续看一下Foundation框架中的常用对象:NSString和NSMutableString. 在OC中 ...

  5. ShellExecute的各种用法

    一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOperation, lpFile, lpParameters, lpDire ...

  6. linux3.0.4编译LDD中的scull全过程

    按照惯例,我是应该先写一些本章的收获的,不过太晚了. 在看完第三章之后开始编译,错误一堆,几乎崩溃,幸亏经过不断的百度,总算解决了问题,我发现 我遇到问题比较多,算是集中七个龙珠了吧,感谢先行的大神们 ...

  7. Yii 1.1 URL两个笔记 同时支持PATH于GET路由和隐藏index.php

    同时支持PATH于GET格式路由(修改框架文件 简直坑) framework/web/CUrlManager.php parseUrl方法 第一行判断修改成 if($this->getUrlFo ...

  8. Unix 环境高级编程---线程创建、同步、

    一下代码主要实现了linux下线程创建的基本方法,这些都是使用默认属性的.以后有机会再探讨自定义属性的情况.主要是为了练习三种基本的线程同步方法:互斥.读写锁以及条件变量. #include < ...

  9. UIView的autoresizingMask属性

    今天做相册列表的时候,发现有些 UITableViewController 属性不好记忆,然后就查找了一些资料.做一下备份. 在 UIView 中有一个autoresizingMask的属性,它对应的 ...

  10. UI进阶 科大讯飞(1) 语音听写(语音转换成文字)

    一.科大讯飞开放平台: http://www.xfyun.cn/ 注册.登录之后创建新应用. 因为本项目只实现了语音听写,所以在SDK下载中心勾选语音听写单项SDK就可以了 开发平台选择iOS,应用选 ...