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 应用运行的比预期慢的时 ...
随机推荐
- OCM读书笔记(2) - PL/SQL 基础
1. % type 用法,提取% type所在字段的类型 declare myid dept.deptno % type; myname dept.dname % type;begin ...
- 王立平--android中的anim(动画)
简单有用步骤: 1.新建anim目录. 2.在anim下新建xml文件, 3.在xml下编写自己须要动画. 简单样例: 给Imageview加入动画 public class MainActivity ...
- hibernate.cfg.xml文件的配置模板和不同数据库的配置參数
(1)hibernate.cfg.xml文件的配置模板 <?xml version="1.0" encoding="UTF-8"?> <!DO ...
- python 多线程一(lock)
''' Created on Jun 17, 2013 @author: smp ''' #-*- coding:utf-8 -*- import threading import time coun ...
- hash应用以及vector的使用简介:POJ 3349 Snowflake Snow Snowflakes
今天学的hash.说实话还没怎么搞懂,明天有时间把知识点总结写了,今天就小小的写个结题报告吧! 题意: 在n (n<100000)个雪花中判断是否存在两片完全相同的雪花,每片雪花有6个角,每个角 ...
- Load and Unload
一.前言 在前一段时间,我遭遇了一个现象诡异的Bug,最后原因归结为在DllMain里错误地调用了FreeLibrary(在本文最后对此Bug有详细的解释). MSDN里关于禁止在DllMain里调用 ...
- poj 1872 A Dicey Problem WA的代码,望各位指教!!!
A Dicey Problem Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 832 Accepted: 278 Des ...
- OCP读书笔记(6) - 手动恢复操作
6.Restore and Recovery Task 非关键性文件丢失的恢复 临时文件丢失的恢复 临时表空间文件丢失的恢复: 查看数据库中的临时文件: SQL> select file#,ST ...
- Managing Data in Containers
Managing Data in Containers So far we've been introduced to some basic Docker concepts, seen how to ...
- VSTO 学习笔记(十)Office 2010 Ribbon开发
原文:VSTO 学习笔记(十)Office 2010 Ribbon开发 微软的Office系列办公套件从Office 2007开始首次引入了Ribbon导航菜单模式,其将一系列相关的功能集成在一个个R ...