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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM