web-dev-qa-db-ja.com

Javaスレッドダンプ:「ロック待機」と「待機待機」の違い?

Javaスレッドダンプでは、スタックトレース内で言及されたロックを確認できます。
3種類の情報があるようです:

1:

- locked <0x00002aab329f7fa0> (a Java.io.BufferedInputStream)

2:

- waiting to lock <0x00002aaaf4ff6fa0> (a org.alfresco.repo.lock.LockServiceImpl)

3:

- parking to wait for  <0x00002aaafbf70bb8> (a Java.util.concurrent.SynchronousQueue$TransferStack)
  • 1:スレッドはオブジェクト0x00002aab329f7fa0のロックを取得しました。
  • 2&3:スレッドは、オブジェクトのロックが利用可能になるのを待っていると言っているようです...
    しかし、2と3の違いは何ですか?
45
Nicolas Raoul

組み込みロックを使用する場合はスレッドダンプで「ロック待ち」となり、Java.util.concurrentからのロックを使用する場合は「待機待ち」となります。次の例について考えてみます。

_import Java.util.concurrent.locks.Lock;
import Java.util.concurrent.locks.ReentrantLock;

public class LockTest {

    final Lock lock = new ReentrantLock(true);

    synchronized void intrinsicLock() {
        Thread th = new Thread(new Runnable() {
            public void run() {
                intrinsicLock();
            }
        }, "My thread");
        th.start();
        try {
            th.join();
        } catch (InterruptedException e) {
        }
    }

    void reentrantLock() {
        lock.lock();
        Thread th = new Thread(new Runnable() {
            public void run() {
                reentrantLock();
            }
        }, "My thread");
        th.start();
        try {
            th.join();
        } catch (InterruptedException e) {
        }
        lock.unlock();
    }


    public static void main(String[] args) {
        LockTest lockTest = new LockTest();
        lockTest.intrinsicLock();
        //lockTest.reentrantLock();
    }

}
_

lockTest.intrinsicLock()を使用すると、次のスレッドダンプが取得されます。

_"My thread" prio=10 tid=0x00007fffec015800 nid=0x1775 waiting for monitor entry [0x00007ffff15e5000]
   Java.lang.Thread.State: BLOCKED (on object monitor)
    at LockTest.intrinsicLock(LockTest.Java:9)
    - waiting to lock <0x00000007d6a33b10> (a LockTest)
    at LockTest$1.run(LockTest.Java:11)
    at Java.lang.Thread.run(Thread.Java:662)
_

lockTest.reentrantLock()が生成する間:

_"My thread" prio=10 tid=0x00007fffec082800 nid=0x17e8 waiting on condition [0x00007ffff14eb000]
   Java.lang.Thread.State: WAITING (parking)
    at Sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007d6a33d30> (a Java.util.concurrent.locks.ReentrantLock$FairSync)
    at Java.util.concurrent.locks.LockSupport.park(LockSupport.Java:156)
    at Java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.Java:811)
    at Java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.Java:842)
    at Java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.Java:1178)
    at Java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.Java:201)
    at Java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.Java:262)
    at LockTest.reentrantLock(LockTest.Java:22)
    at LockTest$2.run(LockTest.Java:25)
    at Java.lang.Thread.run(Thread.Java:662)
_
44
rgerganov

私の考えでは、Java.util.concurrentパッケージは、LockSupport.park()メソッドを使用して、abstractqueuedsynchronizedフレームワークに属するCountDownLatch、ReentrantLockなどのスレッドをブロックします。したがって、質問の3番目のシナリオは、コードが最終的にLockSupport.park()メソッドを呼び出すことを意味します。Java.util.concurrentパッケージのコンカレントクラスを使用する場合、2番目のシナリオは、同期されたキーワークを使用してwait()メソッドを明示的に呼び出すことを意味します。

2
binnchx chen