web-dev-qa-db-fra.com

Java vidage de thread: différence entre "attendre pour verrouiller" et "se garer pour attendre"?

Dans un Java, vous pouvez voir les verrous mentionnés dans les traces de pile.
Il semble y avoir trois types d'informations:

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: le thread a obtenu un verrou sur l'objet 0x00002aab329f7fa0.
  • 2 & 3: On dirait que le thread attend que le verrou sur ledit objet soit disponible ...
    mais quelle est la différence 2 et 3?
45
Nicolas Raoul

Vous obtiendrez "attente de verrouillage" dans le vidage de thread lors de l'utilisation de verrous intrinsèques et "stationnement à attendre" lors de l'utilisation de verrous de Java.util.concurrent. Prenons l'exemple suivant:

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();
    }

}

Avec lockTest.intrinsicLock() vous obtiendrez le vidage de thread suivant:

"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)

tandis que lockTest.reentrantLock() produit:

"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

À mon avis, le package Java.util.concurrent utilise presque la méthode LockSupport.park () pour bloquer les threads, tels que CountDownLatch, ReentrantLock qui appartiennent au framework abstractqueuedsynchronized. Ainsi, le 3ème scénario dans vos questions signifie que votre code appelle finalement la méthode LockSupport.park (), pour que vous utilisiez la classe simultanée dans le package Java.util.concurrent, le 2ème scénario signifie que vous utilisez le travail de clé synchronisé et appelez explicitement la méthode wait ().

2
binnchx chen