Locked ownable synchronizers(转)
public class DeadLock {
public static void main(final String[] args) throws Exception {
final Object lock1 = new Object();
final Object lock2 = new Object();
Thread.currentThread().setName("main-thread");
final Thread r = new Thread("another-thread") {
@Override
public void run() {
try {
synchronized (lock2) {
Thread.sleep(20000);
synchronized (lock1) {
Thread.sleep(20000);
}
}
}
catch (final Exception e) {
e.printStackTrace();
}
}
};
r.start();
Thread.sleep(5000);
synchronized (lock1) {
Thread.sleep(20000);
synchronized (lock2) {
Thread.sleep(20000);
}
}
}
}
这段代码可能有点复杂,但原理不麻烦,就是描述了经典的加锁顺序问题。栈信息比较有趣,裁剪之后如下。
"another-thread" prio= tid=0x02b22400 nid=0x2250 waiting for monitor entry [0x0316f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock$.run(DeadLock.java:)
- waiting to lock <0x22bc3f90> (a java.lang.Object)
- locked <0x22bc3f98> (a java.lang.Object) Locked ownable synchronizers:
- None
"main-thread" prio= tid=0x00868800 nid=0x2634 waiting for monitor entry [0x0098f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock.main(DeadLock.java:)
- waiting to lock <0x22bc3f98> (a java.lang.Object)
- locked <0x22bc3f90> (a java.lang.Object) Locked ownable synchronizers:
- None
Found one Java-level deadlock:
=============================
"another-thread":
waiting to lock monitor 0x02ad433c (object 0x22bc3f90, a java.lang.Object),
which is held by "main-thread"
"main-thread":
waiting to lock monitor 0x02ad363c (object 0x22bc3f98, a java.lang.Object),
which is held by "another-thread" Java stack information for the threads listed above:
===================================================
"another-thread":
at DeadLock$.run(DeadLock.java:)
- waiting to lock <0x22bc3f90> (a java.lang.Object)
- locked <0x22bc3f98> (a java.lang.Object)
"main-thread":
at DeadLock.main(DeadLock.java:)
- waiting to lock <0x22bc3f98> (a java.lang.Object)
- locked <0x22bc3f90> (a java.lang.Object) Found deadlock.
主线程中提示了当前持有的锁和期望获取的锁,而新线程也存在类似的提示,只是获取锁的顺序不同。从栈信息可以看出,两个线程都处于BLOCKED状态。可能是源代码中的问题过于明显,导出的栈信息中给出了死锁的提示信息,实际项目的业务代码比样例要复杂,JVM可能做不到这么智能。这里的提示信息多多少少有点让我失望,在主线程栈信息的最后一部分没有输出当前持有锁的列表,很奇怪,不知道是不是和JDK的实现有关。
import java.security.SecureRandom;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock; public class DeadLock {
private final ReentrantLock lock = new ReentrantLock();
private static final SecureRandom random = new SecureRandom(); public DeadLock() {
} public void runWork() { final ThreadPoolExecutor threadpool = new ThreadPoolExecutor(3, 3, 60L, TimeUnit.DAYS,
new SynchronousQueue<Runnable>(), new ThreadFactory() {
private final AtomicInteger counter = new AtomicInteger(1);
@Override
public Thread newThread(final Runnable r) {
return new Thread(r, "thread-sn-" + counter.getAndIncrement());
}
});
threadpool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
Thread.currentThread().setName("main-thread");
for (int i = 0; i < 15; ++i) {
threadpool.submit(new Runnable() {
@Override
public void run() {
try { int timeout = 0;
while ((timeout = random.nextInt()) <= 0) {
}
timeout = timeout % 111;
Thread.sleep(timeout * 100L); lock.lock();
callLongTime(); }
catch (final Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
});
}
threadpool.shutdown();
} public static void main(final String[] args) throws Exception {
new DeadLock().runWork();
} static long callLongTime() {
System.out.println("thread name " + Thread.currentThread().getName());
long sum = 0;
for (long i = 0; i < 10000000000L; ++i) {
sum = sum ^ i + i;
}
return sum;
}
}
最后一个样例,写的比较复杂,但事情比较简单,线程之间的同步关键字换成了Java5提供的concurrent库中的重入锁。
"thread-sn-3" prio= tid=0x02de8400 nid=0x2688 runnable [0x0320f000]
java.lang.Thread.State: RUNNABLE
at DeadLock.callLongTime(DeadLock.java:)
at DeadLock$.run(DeadLock.java:)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:)
at java.util.concurrent.FutureTask.run(FutureTask.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:) Locked ownable synchronizers:
- <0x22be1488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
- <0x22be66d8> (a java.util.concurrent.ThreadPoolExecutor$Worker) "thread-sn-2" prio= tid=0x02de6c00 nid=0x218c waiting on condition [0x031bf000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x22be1488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:)
at DeadLock$.run(DeadLock.java:)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:)
at java.util.concurrent.FutureTask.run(FutureTask.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:) Locked ownable synchronizers:
- <0x22be64e0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
栈信息比较有趣,JVM在每个线程线的最后部分输出了当前线程持有的锁对象,类型和地址。从上述的信息中可以找到,当前处于运行状态的线程持有了一个地址为0x22be1488的锁,而这个锁正是其它线程等待获取的锁对象。
http://blog.csdn.net/jackie_xiaonan/article/details/8577785
Locked ownable synchronizers(转)的更多相关文章
- 检查死锁与Locked ownable synchronizers(转载)
通过jstack可快速检查线程的死锁信息,用法如下: # 获取JVM ID(JAVA 进程ID),通过参数lv可以获取更详细的JAVA方法调用信息 jps -lv # 得到JVM ID后,执行jsta ...
- 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具
上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...
- jvm系列(四):jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)
文章同步发布于github博客地址,阅读效果更佳,欢迎品尝 运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎 ...
- Java线程问题分析定位
Java线程问题分析定位 分析步骤: 1.使用top命令查看系统资源占用情况,发现Java进程占用大量CPU资源,PID为11572: 2.显示进程详细列表命令:ps -mp 11572 -o THR ...
- 一则JVM memory leak解决的过程
起因是我们的集群应用(3台机器)新版本测试过程中,一般的JVM内存占用 都在1G左右, 但在运行了一段时间后,慢慢升到了4G, 这是一个明显不正常的现象. 定位 过程: 1.先在该机器上按照步骤尝试重 ...
- Java多线程之Runable与Thread
Java多线程是Java开发中的基础内容,但是涉及到高并发就有很深的研究可做了. 最近看了下<Java并发实战>,发先有些地方,虽然可以理解,但是自己在应用中很难下手. 所以还是先回顾一下 ...
- 不正确使用WeakHashMap引起的卡死
公司的jenkins今天出了一点问题,起来以后,总是处于等待状态,所有的任务无法正常加载.登陆界面也出不了.而且cpu占用率100% 把线程导出来,看到: “Loading job NMS_Patch ...
- [已解决] java.net.InetAddress.getHostName() 阻塞问题
在学习java nio的过程中发现某些情况下使用该方法会导致程序阻塞,(情况:服务器,Linux:客户端,WIN10) java.net.InetAddress.getHostName() 阻塞情况如 ...
- 怎样分析java线程堆栈日志
注: 该文章的原文是由 Tae Jin Gu 编写,原文地址为 How to Analyze Java Thread Dumps 当有障碍,或者是一个基于 JAVA 的 WEB 应用运行的比预期慢的时 ...
随机推荐
- [置顶] Asp.Net---css样式的使用方式
Css样式的使用大致分为三种 咱们先来看看一张总括图 1 使用连接的形式调用 有两种发方式调用: A 使用link标签 将样式规则写在.Css的样式文档中,再以<link>标签引入 如 ...
- 带有机器人框架的.NET自己主动化測试
Clayton Neal在软件測试和质量保证方面有超过13年的经验,当中有八年的Windows, web,和移动应用程序的測试自己主动化经验.他在測试领域的全部等级都工作过.近期他在Bloomberg ...
- 虚拟机centOS中安装Redis,主机Redis Destop Manager不能访问虚拟机Redis server的解决方案
今天在学些redis的时候碰到个问题,发现主机Redis Destop Manager不能访问虚拟机Redis server的解决方案,找了一些网上的资料,原因可能有两个,整理记录下来: 1. Red ...
- java基础---->摘要算法的介绍 (转)
数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名.数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密.数据摘要算法也被称为哈希(Hash)算法. ...
- C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET
C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET C++ STL中Map的相关排序操作:按Key排序和按Value排序 分类: C ...
- SilkTest高级进阶系列7-用PostMessage模拟鼠标
SilkTest可以通过调用Windows API来向控件发送消息,从而进行特定的操作.下面这段code使用PostMessage来向计算器上的清除键发送WM_LBUTTONDOWN和WM_LBUTT ...
- servlet其工作原理和例子证明
servlet简单介绍 当我们在地址栏里面输入www.baidu.com,终于呈如今我们面前的是百度搜索的页面.在这些訪问过程中,都会有一个webserver来处理这些请求以及訪问处理后的结果. 而s ...
- 解决ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
在Mac和XAMPP环境,假设终端打字mysql,现这样的问题: ERROR 2002 (HY000): Can't connect to local MySQL server through soc ...
- Linux Shell 之 我的第一个Shell程序
这里我首先会介绍一个Shell是什么,再介绍我的第一个Shell程序和从中总结的经验. 一.Shell是什么 在说我的这个Shell程序之前,还是先跟大家说说什么是Shell吧,相信Shell这个 ...
- tasklet和workqueue的选择
linux内核设计与实现page127中有个比較,内容比較多.概括一下就是1. tasklet不能休眠, 2. 不须要休眠tasklet效率更高 3.有休眠仅仅能workqueue (1)假设不须要休 ...