zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    extern “C”的作用详解
    const和typedef的常见用法详解
    虚函数、纯虚函数、虚函数与析构函数
    C++中四种类型转换方式
    面经中高频知识点归纳(一)
    leetcode Database4
    32位机和64位机下面各类型sizeof的大小
    Spring框架针对dao层的jdbcTemplate操作crud之query查询数据操作
    字符串变量的定义与引用
    使用字符数组及相关函数,求3个国家名中字母顺序排在最前面的国家。
  • 原文地址:https://www.cnblogs.com/softidea/p/4440290.html
Copyright © 2011-2022 走看看