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(转)的更多相关文章

  1. 检查死锁与Locked ownable synchronizers(转载)

    通过jstack可快速检查线程的死锁信息,用法如下: # 获取JVM ID(JAVA 进程ID),通过参数lv可以获取更详细的JAVA方法调用信息 jps -lv # 得到JVM ID后,执行jsta ...

  2. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  3. jvm系列(四):jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)

    文章同步发布于github博客地址,阅读效果更佳,欢迎品尝 运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎 ...

  4. Java线程问题分析定位

    Java线程问题分析定位 分析步骤: 1.使用top命令查看系统资源占用情况,发现Java进程占用大量CPU资源,PID为11572: 2.显示进程详细列表命令:ps -mp 11572 -o THR ...

  5. 一则JVM memory leak解决的过程

    起因是我们的集群应用(3台机器)新版本测试过程中,一般的JVM内存占用 都在1G左右, 但在运行了一段时间后,慢慢升到了4G, 这是一个明显不正常的现象. 定位 过程: 1.先在该机器上按照步骤尝试重 ...

  6. Java多线程之Runable与Thread

    Java多线程是Java开发中的基础内容,但是涉及到高并发就有很深的研究可做了. 最近看了下<Java并发实战>,发先有些地方,虽然可以理解,但是自己在应用中很难下手. 所以还是先回顾一下 ...

  7. 不正确使用WeakHashMap引起的卡死

    公司的jenkins今天出了一点问题,起来以后,总是处于等待状态,所有的任务无法正常加载.登陆界面也出不了.而且cpu占用率100% 把线程导出来,看到: “Loading job NMS_Patch ...

  8. [已解决] java.net.InetAddress.getHostName() 阻塞问题

    在学习java nio的过程中发现某些情况下使用该方法会导致程序阻塞,(情况:服务器,Linux:客户端,WIN10) java.net.InetAddress.getHostName() 阻塞情况如 ...

  9. 怎样分析java线程堆栈日志

    注: 该文章的原文是由 Tae Jin Gu 编写,原文地址为 How to Analyze Java Thread Dumps 当有障碍,或者是一个基于 JAVA 的 WEB 应用运行的比预期慢的时 ...

随机推荐

  1. Linux I/O 重定向详解及应用实例

    Linux I/O 重定向详解及应用实例 简解 > 输出 < 输入 >> 追加 & [> | < | >>]之前:输入输出; ls /dev & ...

  2. HttpWeb服务器之--用OO方式写

    虽然写的不是很好,但 最终解释权以及版权归13东倍所有! package com.web; import java.io.IOException; public class Test { public ...

  3. fopen()功能

    1.2 文件输入和输出功能 键盘.显示器.打印机.磁盘驱动器和其他逻辑器件, 输入和输出可以通过文件管理方法可以完成. 最经常使用的编程是一个磁盘文件, 因此,这一部分主要是基于磁盘文件, 简介Tur ...

  4. linux内核编译环境配置

    linux内核编译环境配置 如果不是编译内核,只需要安装与内核相匹配的kernel-devel开发包即可.即是/lib/modules/`uname -r`/build -> /usr/src/ ...

  5. KMP(Knuth-Morris-Pratt)算法

    一.朴素匹配算法 也就是暴力匹配算法.设匹配字符串的长度为n,模式串的长度为m,在最坏情况下,朴字符串匹配算法执行时间为O((n - m + 1)m). 假设m = n / 2, 那么该算法的复杂度就 ...

  6. 蜘蛛侠天堂,打死我mac键盘

    今天是周末,在我租住的房间,以一个离奇事件. 一个蜘蛛侠天堂,趴在我的假期车窗玻璃,爬下沿着玻璃.特别糟糕.可以飞檐走壁. 可惜体力不支,摔死在我的mac键盘上. 有图有视频. 视频链接:http:/ ...

  7. ssh登录过程详细介绍

    服务器端和客户端就取得了相同的会话密钥和会话 ID .对于后续传输的数据,两端都会使用会话密钥进行加密和解密,保证了数据传送的安全. http://blog.csdn.net/lhq9220/arti ...

  8. [Cocos2d-x]节点的尺寸大小

    作为一个CCNode,本身没有大小而言,但是AddChild之后,便有了尺寸的概念. Cocos2d-x中对于一个节点的尺寸可以通过以下三个方法获取: CCSprite: getContentSize ...

  9. GitHub上最火的74个Android开源项目

    GitHub上最火的74个Android开源项目 1.ActionBarSherlock ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库, ...

  10. HDU 3639 Hawk-and-Chicken(良好的沟通)

    HDU 3639 Hawk-and-Chicken 题目链接 题意:就是在一个有向图上,满足传递关系,比方a->b, b->c,那么c能够得到2的支持,问得到支持最大的是谁,而且输出这些人 ...