Java多线程(五):死锁
死锁
概念
当线程Thread-0持有锁Lock1,Thread-1持有锁Lock2,此时Thread-0申请Lock2锁的使用权,Thread-1申请Lock1锁的使用权,Thread-0和Thread-1都在无限地等待锁的使用权。这样就造成了死锁。

死锁是主要由于设计的问题。一旦出现死锁,死锁的线程就会永远不能使用,同步方法不会被执行,死锁线程不会被自动终止,无尽地消耗CPU资源。
例子
看一个例子
ThreadDomain29类,模拟图片中,线程持有一个锁,申请被其他线程持有的锁的情况
public class ThreadDomain29 {
private final Object obj1 = new Object();
private final Object obj2 = new Object();
public void obj1obj2() throws Exception
{
synchronized (obj1)
{
Thread.sleep(2000);
synchronized (obj2)
{
System.out.println("obj1obj2 end!");
}
}
}
public void obj2obj1() throws Exception
{
synchronized (obj2)
{
Thread.sleep(2000);
synchronized (obj1)
{
System.out.println("obj2obj1 end!");
}
}
}
}
MyThread29_0类
public class MyThread29_0 extends Thread{
private ThreadDomain29 dl;
public MyThread29_0(ThreadDomain29 dl)
{
this.dl = dl;
}
public void run()
{
try
{
dl.obj1obj2();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
MyThread29_1类
public class MyThread29_1 extends Thread{
private ThreadDomain29 dl;
public MyThread29_1(ThreadDomain29 dl)
{
this.dl = dl;
}
public void run()
{
try
{
dl.obj2obj1();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
main方法
public class MyThread29_main {
public static void main(String[] args)
{
ThreadDomain29 dl = new ThreadDomain29();
MyThread29_0 t0 = new MyThread29_0(dl);
MyThread29_1 t1 = new MyThread29_1(dl);
t0.start();
t1.start();
while(true);
}
}
因为发生了死锁,所以你不会看到任何结果。
死锁排查
jps+jstack
jps找到进程id

jstack打印堆栈
输入jstack 10208

可以看到,找到了两个死锁。
JConsole
命令行输入JConsole

点击“检测死锁”

已经检测到了死锁

Java Visual VM
命令行输入jvisualvm
找到我们的进程

自动检测到死锁,推荐使用这种方式
死锁避免
1.尽量少用嵌套的锁。
2.如果一定要用嵌套锁,那么请规定好获取锁的顺序。例子如下:
//伪代码
//condition1可以是属性值大小,hash值大小的比较等等
if(condition1){
synchronized (obj2)
{
Thread.sleep(2000);
synchronized (obj1)
{
System.out.println("obj2obj1 end!");
}
}
}else{
synchronized (obj1)
{
Thread.sleep(2000);
synchronized (obj2)
{
System.out.println("obj1obj2 end!");
}
}
}
3.使用Lock的tryLock方法,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
后面讲到ReentrantLock会详细分析。
Java多线程(五):死锁的更多相关文章
- Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock
在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...
- java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)
对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...
- java多线程(五)之总结(转)
引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...
- Java多线程(五) —— 线程并发库之锁机制
参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...
- java多线程之死锁
产生死锁的条件: 1.有至少一个资源不能共享2.至少有一个任务必须持有一个资源并且等待获取另一个被别的任务持有的资源3.资源不能任务抢占4.必须有循环等待 只要打破其中一个条件就不会产生死锁,通常是打 ...
- Java多线程和死锁
一 .多线程: 售票窗口简单实例: public class SaleTicket { public static class Sale implements Runnable{ ; // @Over ...
- Java多线程:死锁
周末看到一个用jstack查看死锁的例子.昨天晚上总结了一下jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令.供大家参考 1.Jstack 1.1 jstack能得到运行j ...
- Java 多线程(五)之 synchronized 的使用
目录 1 线程安全 2 互斥锁 3 内置锁 synchronized 3.1 普通同步方法,锁是当前实例对象(this) 3.1.1 验证普通方法中的锁的对象是同一个. 3.1.2 验证不同的对象普通 ...
- JAVA多线程----用--死锁
(1) 互斥条件:一个资源每次只能被一个进程使用.(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放.(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺.(4) ...
- Java多线程:线程死锁
发生死锁的原因通常是两个对象的锁相互等待造成的. 以下用一个实例来构造这样的情况: package basic.e_deadlock; import org.apache.log4j.Logger; ...
随机推荐
- doesn't contain a valid partition table 解决方法
输入 fdisk -l 可以看到 输入 fdisk /dev/xvdb 跟着向导一步步做下去(如果不知道该输入什么,就输入“m”并回车,可以打印出菜单): Command (m for help): ...
- uwp 获取系统字体库
原文:uwp 获取系统字体库 效果图: 要获取到字体库首先要在 NuGet 添加 SharpDx.Direct2D1 api: /// <summary> /// 获取系统字体库列表 / ...
- ubuntu下建立golang的build脚本
在不在os中设置gopath,goroot的情况下 建立build.sh文件,文件内容如下: export GOARCH="386"export GOBIN="/home ...
- Visual Studio一直弹出“未将对象引用设置到对象的实例”对话框的处理
试了一下,VS2017更新到最新版本的时候,会有这个错误.相当于是相当编辑XAML界面的时候会弹出,程序真正执行的时候反而不会弹出. 应该是最新的VS2017在显示XAML编辑界面的时候,会执行一部分 ...
- WebAPI增加Area以支持无限层级同名Controller
原文:WebAPI增加Area以支持无限层级同名Controller 微软的WebAPI默认实现逻辑 默认实现中不支持同名Controller,否则在访问时会报HttpError,在网上找到了各种路由 ...
- C# ACCESS 修改表记录提示"UPDATE 语句语法错"问题
错误的sql 语句如下: sqlStr = "update tb_userInfo set passWord='" + pw + "' where userName=' ...
- Linux基础命令杂记
今天又一次搞Linux生产环境搭建.这是种步骤很多,很繁琐而且又不得不做的事情.虽然做过很多次,但还是有很多步骤.命令不记得,每一次到处找资料很麻烦,于是将一些步骤记下,以便查找. 登录远程MySQL ...
- 简单封装 Delphi 的 DirectX类
var CreatorRenderer : TCreatorRenderer; Form1: TForm1; 窗体代码: {$R *.dfm} procedure TForm1.FormCreate ...
- C#调用记事本并填写内容
using System.Runtime.InteropServices; using System.Diagnostics; [DllImport("User32.DLL") ...
- scrapy爬虫框架研究!
最近由于项目需要,开始研究scrapy爬虫,走过不少弯路,准备写个记录,记下踩过的各种坑.