java 分析java死锁_Java死锁示例–如何分析死锁情况

java 分析java死锁

死锁是两个线程或多个线程永远被阻塞的编程情况,这种情况发生在至少两个线程和两个或更多资源的情况下。 在这里,我编写了一个简单的程序,它将导致死锁情况,然后我们将看到如何对其进行分析。

Java死锁示例

package com.journaldev.threads;
public class ThreadDeadlock {public static void main(String[] args) throws InterruptedException {Object obj1 = new Object();Object obj2 = new Object();Object obj3 = new Object();Thread t1 = new Thread(new SyncThread(obj1, obj2), 't1');Thread t2 = new Thread(new SyncThread(obj2, obj3), 't2');Thread t3 = new Thread(new SyncThread(obj3, obj1), 't3');t1.start();Thread.sleep(5000);t2.start();Thread.sleep(5000);t3.start();}
}
class SyncThread implements Runnable{private Object obj1;private Object obj2;public SyncThread(Object o1, Object o2){this.obj1=o1;this.obj2=o2;}@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name + ' acquiring lock on '+obj1);synchronized (obj1) {System.out.println(name + ' acquired lock on '+obj1);work();System.out.println(name + ' acquiring lock on '+obj2);synchronized (obj2) {System.out.println(name + ' acquired lock on '+obj2);work();}System.out.println(name + ' released lock on '+obj2);}System.out.println(name + ' released lock on '+obj1);System.out.println(name + ' finished execution.');}private void work() {try {Thread.sleep(30000);} catch (InterruptedException e) {e.printStackTrace();}}
}

在上面的程序中,SyncThread实现了Runnable接口,并且通过使用同步块一个接一个地获取对每个对象的锁定,从而对两个对象起作用。

在main方法中,我为SyncThread运行了三个线程,并且每个线程之间都有一个共享资源。 线程以这样的方式运行:它将能够获取第一个对象上的锁,但是当它试图获取第二个对象上的锁时,它将进入等待状态,因为它已经被另一个线程锁定了。 这对导致死锁的线程之间的资源形成了循环依赖性。

当我执行上面的程序时,这里是生成的输出,但是由于死锁,程序永远不会终止。

t1 acquiring lock on java.lang.Object@6d9dd520
t1 acquired lock on java.lang.Object@6d9dd520
t2 acquiring lock on java.lang.Object@22aed3a5
t2 acquired lock on java.lang.Object@22aed3a5
t3 acquiring lock on java.lang.Object@218c2661
t3 acquired lock on java.lang.Object@218c2661
t1 acquiring lock on java.lang.Object@22aed3a5
t2 acquiring lock on java.lang.Object@218c2661
t3 acquiring lock on java.lang.Object@6d9dd520

在这里,我们可以从输出中清楚地确定死锁情况,但是在实际应用中,很难找到死锁情况并对其进行调试。

分析死锁

为了分析死锁,我们需要查看应用程序的Java线程转储 ,在上一篇文章中,我解释了如何使用VisualVM Profiler或jstack实用程序生成线程转储 。

这是上面程序的线程转储。

2012-12-27 19:08:34
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):
'Attach Listener' daemon prio=5 tid=0x00007fb0a2814000 nid=0x4007 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE
'DestroyJavaVM' prio=5 tid=0x00007fb0a2801000 nid=0x1703 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE
't3' prio=5 tid=0x00007fb0a204b000 nid=0x4d07 waiting for monitor entry [0x000000015d971000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f658> (a java.lang.Object)- locked <0x000000013df2f678> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
't2' prio=5 tid=0x00007fb0a1073000 nid=0x4207 waiting for monitor entry [0x000000015d209000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f678> (a java.lang.Object)- locked <0x000000013df2f668> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
't1' prio=5 tid=0x00007fb0a1072000 nid=0x5503 waiting for monitor entry [0x000000015d86e000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f668> (a java.lang.Object)- locked <0x000000013df2f658> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
'Service Thread' daemon prio=5 tid=0x00007fb0a1038000 nid=0x5303 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE
'C2 CompilerThread1' daemon prio=5 tid=0x00007fb0a1037000 nid=0x5203 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE
'C2 CompilerThread0' daemon prio=5 tid=0x00007fb0a1016000 nid=0x5103 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE
'Signal Dispatcher' daemon prio=5 tid=0x00007fb0a4003000 nid=0x5003 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE
'Finalizer' daemon prio=5 tid=0x00007fb0a4800000 nid=0x3f03 in Object.wait() [0x000000015d0c0000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)- locked <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
'Reference Handler' daemon prio=5 tid=0x00007fb0a4002000 nid=0x3e03 in Object.wait() [0x000000015cfbd000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000013de75320> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:503)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)- locked <0x000000013de75320> (a java.lang.ref.Reference$Lock)
'VM Thread' prio=5 tid=0x00007fb0a2049800 nid=0x3d03 runnable
'GC task thread#0 (ParallelGC)' prio=5 tid=0x00007fb0a300d800 nid=0x3503 runnable
'GC task thread#1 (ParallelGC)' prio=5 tid=0x00007fb0a2001800 nid=0x3603 runnable
'GC task thread#2 (ParallelGC)' prio=5 tid=0x00007fb0a2003800 nid=0x3703 runnable
'GC task thread#3 (ParallelGC)' prio=5 tid=0x00007fb0a2004000 nid=0x3803 runnable
'GC task thread#4 (ParallelGC)' prio=5 tid=0x00007fb0a2005000 nid=0x3903 runnable
'GC task thread#5 (ParallelGC)' prio=5 tid=0x00007fb0a2005800 nid=0x3a03 runnable
'GC task thread#6 (ParallelGC)' prio=5 tid=0x00007fb0a2006000 nid=0x3b03 runnable
'GC task thread#7 (ParallelGC)' prio=5 tid=0x00007fb0a2006800 nid=0x3c03 runnable
'VM Periodic Task Thread' prio=5 tid=0x00007fb0a1015000 nid=0x5403 waiting on condition
JNI global references: 114
Found one Java-level deadlock:
=============================
't3':waiting to lock monitor 0x00007fb0a1074b08 (object 0x000000013df2f658, a java.lang.Object),which is held by 't1'
't1':waiting to lock monitor 0x00007fb0a1010f08 (object 0x000000013df2f668, a java.lang.Object),which is held by 't2'
't2':waiting to lock monitor 0x00007fb0a1012360 (object 0x000000013df2f678, a java.lang.Object),which is held by 't3'
Java stack information for the threads listed above:
===================================================
't3':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f658> (a java.lang.Object)- locked <0x000000013df2f678> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
't1':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f668> (a java.lang.Object)- locked <0x000000013df2f658> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
't2':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f678> (a java.lang.Object)- locked <0x000000013df2f668> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722)
Found 1 deadlock.

线程转储输出清楚地显示了死锁情况,并且所涉及的线程和资源导致了死锁情况。

为了分析死锁,我们需要寻找状态为BLOCKED的线程,然后寻找等待锁定的资源,每个资源都有一个唯一的ID,通过它我们可以找到哪个线程已经在对象上持有锁。 例如,线程“ t3”正在等待锁定0x000000013df2f658,但它已被线程“ t1”锁定。

一旦分析了死锁情况并找出了导致死锁的线程,就需要进行代码更改以避免死锁情况。

避免死锁

这些是我们可以避免大多数僵局情况的一些准则。

  • 避免嵌套锁 :这是导致死锁的最常见原因,如果已经持有另一个资源,请避免锁定另一个资源。 如果仅使用一个对象锁,则几乎不可能出现死锁情况。 例如,这是不带嵌套锁的run()方法的另一种实现,并且程序成功运行且没有死锁情况。
    public void run() {String name = Thread.currentThread().getName();System.out.println(name + ' acquiring lock on ' + obj1);synchronized (obj1) {System.out.println(name + ' acquired lock on ' + obj1);work();}System.out.println(name + ' released lock on ' + obj1);System.out.println(name + ' acquiring lock on ' + obj2);synchronized (obj2) {System.out.println(name + ' acquired lock on ' + obj2);work();}System.out.println(name + ' released lock on ' + obj2);System.out.println(name + ' finished execution.');}
  • 仅锁定所需条件 :您应该仅对必须处理的资源获取锁定,例如,在上述程序中,我正在锁定完整的Object资源,但是如果我们仅对其中一个字段感兴趣,则应该仅锁定该对象具体字段不完整的对象。
  • 避免无限期地等待 :如果两个线程正在使用线程连接无限期地等待彼此完成,则可能会陷入死锁。 如果您的线程必须等待另一个线程完成,则始终最好使用join并在等待线程完成的最长时间内使用它。

参考: Java死锁示例–如何从我们的JCG合作伙伴 Pankaj Kumar的Developer Recipes博客上分析死锁情况 。

翻译自: https://www.javacodegeeks.com/2013/01/java-deadlock-example-how-to-analyze-deadlock-situation.html

java 分析java死锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

insert 多条数据 并且具有唯一标识符

DECLARE COUNT INT DECLARE NAME NVARCHAR(10) SET COUNT0 WHILE COUNT<1000 BEGIN SET NAMESYSTEMCAST(COUNT AS NVARCHAR(10)) INSERT INTO dbo.users VALUES (NEWID(),NAME,123123COUNT,DATEADD(DAY,COUNT,2012-12-12),GETDATE()) SET COUNT COUNT 1 END 转载于:http…

Java Message System简介

Java消息系统 在本文中&#xff0c;我将讨论面向消息的中间件 &#xff08;MOM&#xff09;以及JMS如何在Enterprise Java中实现它。 另外&#xff0c;我将讨论适合JMS使用的典型用例以及用于讨论消息传递解决方案的不同术语&#xff0c;例如Publisher / Sender &#xff0c; D…

FLV协议5分钟入门浅析

FLV协议简介 FLV&#xff08;Flash Video&#xff09;是一种流媒体格式&#xff0c;因其体积小、协议相对简单&#xff0c;很快便流行开来&#xff0c;并得到广泛的支持。 常见的HTTP-FLV直播协议&#xff0c;就是使用HTTP流式传输通过FLV封装的音视频数据。对想要了解HTTP-FLV…

问题 1049: [编程入门]结构体之时间设计

题目描述定义一个结构体变量&#xff08;包括年、月、日&#xff09;。计算该日在本年中是第几天&#xff0c;注意闰年问题。输入年月日输出当年第几天样例输入2000 12 31 样例输出366 import java.util.Scanner; public class Main{ public static void main(String args[]){ …

反序列化 jackson_使用Jackson和Super类型令牌的Json反序列化

反序列化 jacksonDatatables是一个jquery插件&#xff0c;用于显示表格信息–它可以增强简单的表或可以使用基于AJAX的数据并以表格形式显示信息。 数据表要​​求来自服务器的数据遵循特定的JSON格式才能在屏幕上显示。 考虑要显示Member实体列表的情况&#xff0c;那么Membe…

NOIP模拟测试18「引子·可爱宝贝精灵·相互再归的鹅妈妈」

待补 引子 题解 大模拟&#xff0c;注意细节 代码1 #include<bits/stdc.h> using namespace std; int n,m;char a[1005][1005];bool vst[1005][1005]; void solve(int na,int nb) {int ina,jnb,now0;while(1){j;if(a[na][j])break;}while(1){i;if(a[i][nb])break;}for(in…

GC解释:收集器概述

当前版本的HotSpot JVM包括三种类型的垃圾收集器&#xff1a; –串行收集器 –并行收集器 –多数同时收集者 它们都是世代的&#xff0c;这意味着它们利用了堆的划分方式 。 垃圾收集器负责三个主要操作&#xff1a; –查找不再使用的对象 –释放这些对象之后的内存 –…

数据结构之排序五:选择排序

def selectedSort(myList):#获取list的长度length len(myList)#一共进行多少轮比较for i in range(0,length-1):#默认设置最小值得index为当前值smallest i#用当先最小index的值分别与后面的值进行比较,以便获取最小indexfor j in range(i1,length):#如果找到比当前值小的ind…

C#代码规范

1. 引言 本文是一套面向C# programmer 和C# developer 进行开发所应遵循的开发规范。 按照此规范来开发C#程序可带来以下益处&#xff1a; 代码的编写保持一致性&#xff0c; 提高代码的可读性和可维护性&#xff0c; 在团队开发一个项目的情况下&a…

谷歌guava_使用Google Guava进行馆藏创建和不变性

谷歌guava因此&#xff0c;我想看看番石榴提供的一些集合创建模式&#xff0c;以及它提供的某些不可变集合类型。 如果您没有看过我以前的文章&#xff0c;则可能要从这里开始&#xff1a; 番石榴第1部分– MultiMaps 番石榴第2部分– BiMaps 番石榴第3部分–多组 Guava的…

问题 1051: [编程入门]结构体之成绩统计2

题目描述有N个学生&#xff0c;每个学生的数据包括学号、姓名、3门课的成绩&#xff0c;从键盘输入N个学生的数据&#xff0c;要求打印出3门课的总平均成绩&#xff0c;以及最高分的学生的数据&#xff08;包括学号、姓名、3门课成绩&#xff09;输入学生数量N占一行每个学生的…

socket-02

# -- coding: utf-8 --_author__ "HuaQiang Yan" import socketdef handle_request(client):buf client.recv(1024) # 接收请求client.send(bytes("HTTP/1.1 200 OK\r\n\r\n", encodingutf-8))client.send(bytes("Hello World&#xff01;", …

jenkins复制作业_Jenkins分层作业和作业状态汇总

jenkins复制作业您可能知道&#xff0c;Jenkins是高度可配置的CI服务器。 我们可以设置不同的自定义构建过程。 我将分享一些我用来设置詹金斯工作层次的方法。 这是用例&#xff1a; 我们有一个主要的入口工作被调用以启动整个构建过程。 这项工作可以有一个到多个子工作。 …

xaml语言建立首个win8 Metro应用,rss阅读器

本实例是来源msdn的Metro开发文档&#xff0c;按着解说一步步来理解的&#xff0c;修改了一点点&#xff0c;拿了博客园本人的博客作为RSS阅读&#xff0c;本实例用来学习还是可以的 参考文档http://msdn.microsoft.com/zh-cn/library/windows/apps/br211380.aspx#Y909 先看允…

在扩展Spock时输出给定值

Spock是一个Java测试框架&#xff0c;由GradleWare的软件工程师Peter Niederwieser于2008年创建&#xff0c;它可以促进BDD的发展。 利用这个 例如 &#xff0c;一个故事可以定义为&#xff1a; Story: Returns go to stockAs a store owner In order to keep track of stock…

wsgi

wsgi&#xff0c;通用网关接口。相当于在app与web服务&#xff08;socket服务端&#xff09;之间建立统一连接的规范。 真实开发中的python web程序来说&#xff0c;一般会分为两部分&#xff1a;服务器程序和应用程序。服务器程序负责对socket服务器进行封装&#xff0c;并在请…

Java与Python:哪一种最适合您? [信息图]

通过从应用程序中学习企业APM产品&#xff0c;发现更快&#xff0c;更高效的性能监控。 参加AppDynamics APM导览&#xff01; 在软件开发中&#xff0c;很少有问题比选择编程语言更具分裂性或部落性。 软件开发人员经常以自己选择的工具来强烈地认同自己&#xff0c;将客观事…

零基础学习java------day11------常用API

API概述 API(application Programming Interface, 应用程序编程接口)&#xff0c;是一些预先定义的函数。目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节 比如我需要在一个程序里面嵌入…

.net 下的集合

集合的操作在编码的时候很常见。但是由于经常使用几种集合。而忽略了一些不常用的集合。在这里我整理下。 首先先了解下接口&#xff1a; 1、IEnumerable&#xff0c;返回一个循环访问集合的枚举器。 2、IEnumerable<T>&#xff0c;返回一个循环访问指定集合T的枚举器。 …

aspects_具有Aspects的Java中的Mixin –用于Scala特性示例

aspectsScala特征允许将新行为混合到一个类中。 考虑两个特征&#xff0c;可以向JPA实体添加审核和与版本相关的字段&#xff1a; package mvcsample.domainimport javax.persistence.Version import scala.reflect.BeanProperty import java.util.Datetrait Versionable {Ver…