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=6 tid=0x02b22400 nid=0x2250 waiting for monitor entry [0x0316f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at DeadLock$1.run(DeadLock.java:14)
    - waiting to lock <0x22bc3f90> (a java.lang.Object)
    - locked <0x22bc3f98> (a java.lang.Object)

   Locked ownable synchronizers:
    - None
"main-thread" prio=6 tid=0x00868800 nid=0x2634 waiting for monitor entry [0x0098f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at DeadLock.main(DeadLock.java:28)
    - 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$1.run(DeadLock.java:14)
    - waiting to lock <0x22bc3f90> (a java.lang.Object)
    - locked <0x22bc3f98> (a java.lang.Object)
"main-thread":
    at DeadLock.main(DeadLock.java:28)
    - waiting to lock <0x22bc3f98> (a java.lang.Object)
    - locked <0x22bc3f90> (a java.lang.Object)

Found 1 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=6 tid=0x02de8400 nid=0x2688 runnable [0x0320f000]
   java.lang.Thread.State: RUNNABLE
    at DeadLock.callLongTime(DeadLock.java:63)
    at DeadLock$2.run(DeadLock.java:41)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

   Locked ownable synchronizers:
    - <0x22be1488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    - <0x22be66d8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"thread-sn-2" prio=6 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:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
    at DeadLock$2.run(DeadLock.java:40)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

   Locked ownable synchronizers:
    - <0x22be64e0> (a java.util.concurrent.ThreadPoolExecutor$Worker)

栈信息比较有趣,JVM在每个线程线的最后部分输出了当前线程持有的锁对象,类型和地址。从上述的信息中可以找到,当前处于运行状态的线程持有了一个地址为0x22be1488的锁,而这个锁正是其它线程等待获取的锁对象。

 

http://blog.csdn.net/jackie_xiaonan/article/details/8577785

 

时间: 2024-09-20 08:05:59

Locked ownable synchronizers(转)的相关文章

runnable-线程一直处于RUNNABLE,也没有发现阻塞或是死锁的情况?

问题描述 线程一直处于RUNNABLE,也没有发现阻塞或是死锁的情况? 我写的是一个频繁访问网络的爬虫,启了20个线程: 但是老实跑了一段时间,线程全部处于RUNNABLE状态了: 网络使用的是httpclient3.1; 我把threaddump给放到下面: "Thread-19" #30 prio=5 os_prio=0 tid=0x0000000059b3d000 nid=0xcb4 runnable [0x000000005ba1e000] java.lang.Thread.S

Java 程序死锁问题原理及解决方案

 Java 语言通过 synchronized 关键字来保证原子性,这是因为每一个 ob ject 都有一个隐含的锁,这个也称作监视器对象.在进入 synchronized 之前自动获取此内部锁,而一旦离开此方式,无论是完成或者中断都会自动释放锁.显然这是一个独占锁,每个锁请求之间是互斥的.相对于众多高级锁 (Lock/ReadWriteLock 等),synchronized 的代价都比后者要高.但是 synchronzied 的语法比较简单,而且也比较容易使用和理解.Lock 一旦调用了 l

发布或重启线上服务时抖动问题解决方案

一.问题描述       在发布或重启某线上某服务时(jetty8作为服务器),常常发现有些机器的load会飙到非常高(高达70),并持续较长一段时间(5分钟)后回落(图1),与此同时响应时间曲线(图2)也与load曲线一致.注:load飙高的初始时刻是应用服务端口打开,流量打入时(load具体指什么可参考http://www.cnblogs.com/amsun/p/3155246.html).   图1 发布时候load飙高   图2 发布时候响应时间飙高   二.问题排查方法      发布

急求。。。。。看下java的dump文件,会这样

问题描述 急求.....看下java的dump文件,会这样 2015-03-18 22:38:54 Full thread dump Java HotSpot(TM) Client VM (20.1-b02 mixed mode, sharing): "Attach Listener" daemon prio=10 tid=0x089f1c00 nid=0x1df1 waiting on condition [0x00000000] java.lang.Thread.State: RU

性能分析系列-小命令保证大性能 | 程超

编者按:程超在圈里有读三遍经典文章的习惯,江湖人称三遍哥,程超作为易宝支付的架构师,有10多年的JAVA开发经历,专注于金融支付与大数据领域,他将工作之中遇到的问题和经验都分享在简书(小程故事多)里面,小编略微采集小部分放到中生代公众号里,以飨读者! 最近在工作中经常和性能压测工作打交道,积累了一些性能分析经验,我觉得这些经验对每一个开发者都有帮助的,能开发出性能高的代码也是我们的最终目标. 由易到难,我们逐步介绍不同命令的用法和好处,这些命令是如何帮助我们开发人员进行性能分析的. 一.开发者的

怎样使用jstack诊断Java应用程序故障(转)

          最近一段时间,我们的生产系统升级频繁出现故障,具体故障现象是启动后10来分钟就出现交易缓慢,处理线程耗尽等现象,并且故障发生的频率蛮高的.经过详细的诊断和排查,终于发现了问题,是groovy在osgi中运行会出现classloader死锁,最后我们也解决了这个问题.         如果单靠通过查看代码是很难去发现这个问题,在这一次故障排查中,我也学到了怎样更好的使用jvm监控工具来进行诊断,主要用到了jstack和jmap命令,jmap上次已经讲过就不再讲了,下面就一个例子

关于访问数据库的线程卡死的疑问

问题描述 关于访问数据库的线程卡死的疑问 "http-nio-8080-exec-5" #82 daemon prio=5 os_prio=0 tid=0x00007f7a18004800 nid=0x7be5 runnable [0x00007f79a1459000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketI

Java Thread 那些事

        这篇文章被压在草稿箱许久,最近公司内部的技术社区有同学贴出了几篇分享Java线程的文章,发觉有很多的地方可以深挖,所以花点时间继续撰写,便有了这篇博文.本文只聚焦JVM层面的线程模型,不考虑和真实的操作系统Thread模型挂钩(由于篇幅有限,本文不会介绍Thread dump结构,也不会介绍调优过程中对工具的综合使用,如ps,perf.top,iostat,jstack,TDA plugin,Thread inspector.如果有问题,欢迎大家留言交流).后面会考虑对xUnix

hibernate-单线程循环假死,纠结了一星期了,求指导

问题描述 单线程循环假死,纠结了一星期了,求指导 现在我正在维护一个派单系统,派单的业务逻辑是新起了一个线程,这个派单线程并没有 用到线程池之类的技术,就是一个很简单的new Thread().start(),然后有一个监听线程观察 该线程是否存活,如果不存活就重新再创建一个派单线程,但是现在有一个奇怪的问题,就是 运行大概一天左右,派单线程就会出现假死状态,但是通过ThreadDump发现该线程的状态 是Running,而每次派单线程都卡在一个Hibernate的get查询上,并且Thread