Анализ исходного ΠΊΠΎΠ΄Π° CountDownLatch сСрии Dead Java Synchronization

Java

πŸ–•ΠŸΡ€ΠΈΠ³Π»Π°ΡˆΠ°Π΅ΠΌ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΌΠΎΠΉ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹ΠΉ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚ Β«Π‘Ρ€Π°Ρ‚ Π’ΠΎΠ½Π³ Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ исходный ΠΊΠΎΠ΄Β», ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΡΡ‚Π°Ρ‚ΡŒΡΠΌΠΈ ΠΈΠ· сСрии исходного ΠΊΠΎΠ΄Π° ΠΈ ΠΏΠΎΠΏΠ»Π°Π²Π°Ρ‚ΡŒ Π² ΠΎΠΊΠ΅Π°Π½Π΅ исходного ΠΊΠΎΠ΄Π° вмСстС с Π±Ρ€Π°Ρ‚ΠΎΠΌ Π’ΠΎΠ½Π³ΠΎΠΌ.

(ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ исходный ΠΊΠΎΠ΄ Π½Π° Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½ΠΎΠΌ экранС мобильного Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π°)


ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°

(1) Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ CountDownLatch?

(2) КакиС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΅ΡΡ‚ΡŒ Ρƒ CountDownLatch?

(3) Π’ ΠΊΠ°ΠΊΠΈΡ… сцСнариях ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ CountDownLatch?

(4) МоТно Π»ΠΈ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ счСт CountDownLatch?

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

CountDownLatch ΠΌΠΎΠΆΠ½ΠΎ пСрСвСсти ΠΊΠ°ΠΊ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ отсчСта, Π½ΠΎ это каТСтся Π½Π΅Ρ‚ΠΎΡ‡Π½Ρ‹ΠΌ, Π΅Π³ΠΎ смысл Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΈΠ»ΠΈ нСскольким ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.

ΠžΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ использованиС CountDownLatch нСсколько ΠΏΠΎΡ…ΠΎΠΆΠ΅ Π½Π° Thread.join(), оТидая Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ основной Π·Π°Π΄Π°Ρ‡ΠΈ.

структура класса

CountDownLatch

CountDownLatch содСрТит Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ класс Sync, Ρƒ Π½Π΅Π³ΠΎ Π½Π΅Ρ‚ справСдливого/нСсправСдливого Ρ€Π΅ΠΆΠΈΠΌΠ°, поэтому это ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ простой синхронизатор.

Π’Π°ΠΊΠΆΠ΅ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ CountDownLatch Π½Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ интСрфСйс Serializable, поэтому Π΅Π³ΠΎ нСльзя ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ.

Анализ исходного ΠΊΠΎΠ΄Π°

Бинхронизация Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ класса

private static final class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 4982264981922014374L;
    
    // δΌ ε…₯εˆε§‹ζ¬‘ζ•°
    Sync(int count) {
        setState(count);
    }
    // θŽ·ε–θΏ˜ε‰©ηš„ζ¬‘ζ•°
    int getCount() {
        return getState();
    }
    // ε°θ―•θŽ·ε–ε…±δΊ«ι”
    protected int tryAcquireShared(int acquires) {
        // ζ³¨ζ„οΌŒθΏ™ι‡Œstateη­‰δΊŽ0ηš„ζ—Άε€™θΏ”ε›žηš„ζ˜―1,也就是说count减为0ηš„ζ—Άε€™θŽ·ε–ζ€»ζ˜―ζˆεŠŸ
        // stateδΈη­‰δΊŽ0ηš„ζ—Άε€™θΏ”ε›žηš„ζ˜―-1,也就是count不为0ηš„ζ—Άε€™ζ€»ζ˜―θ¦ζŽ’ι˜Ÿ
        return (getState() == 0) ? 1 : -1;
    }
    // ε°θ―•ι‡Šζ”Ύι”
    protected boolean tryReleaseShared(int releases) {
        for (;;) {
            // stateηš„ε€Ό
            int c = getState();
            // η­‰δΊŽ0δΊ†οΌŒεˆ™ζ— ζ³•ε†ι‡Šζ”ΎδΊ†
            if (c == 0)
                return false;
            // ε°†countηš„ε€Όε‡1
            int nextc = c-1;
            // εŽŸε­ζ›΄ζ–°stateηš„ε€Ό
            if (compareAndSetState(c, nextc))
                // 减为0ηš„ζ—Άε€™θΏ”ε›žtrueοΌŒθΏ™ζ—ΆδΌšε”€ι†’εŽι’ζŽ’ι˜Ÿηš„ηΊΏη¨‹
                return nextc == 0;
        }
    }
}

Бинхронизация пСрСопрСдСляСт ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ tryAcquireShared() ΠΈ tryReleaseShared() ΠΈ сохраняСт количСство Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ состояния.

Π—Π΄Π΅ΡΡŒ слСдуСт ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π΄Π²ΡƒΡ… Π²Ρ‹ΡˆΠ΅ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² бСсполСзны.

ΠœΠ΅Ρ‚ΠΎΠ΄ ΡΡ‚Ρ€ΠΎΠΈΡ‚Π΅Π»ΡŒΡΡ‚Π²Π°

public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}

ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΡ€ΠΎΠΉΡ‚ΠΈ счСт, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ являСтся Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΌ числом.

ΠΌΠ΅Ρ‚ΠΎΠ΄ оТидания()

// java.util.concurrent.CountDownLatch.await()
public void await() throws InterruptedException {
    // 调用AQSηš„acquireSharedInterruptibly()方法
    sync.acquireSharedInterruptibly(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly()
public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    // ε°θ―•θŽ·ε–ι”οΌŒε¦‚ζžœε€±θ΄₯εˆ™ζŽ’ι˜Ÿ
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}

ΠœΠ΅Ρ‚ΠΎΠ΄ await() – это ΠΌΠ΅Ρ‚ΠΎΠ΄ оТидания Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Π‘Π½Π°Ρ‡Π°Π»Π° ΠΎΠ½ попытаСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΎΠ±Ρ‰ΡƒΡŽ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ. Π’ случаС Π½Π΅ΡƒΠ΄Π°Ρ‡ΠΈ ΠΎΠ½ Π²ΠΎΠΉΠ΄Π΅Ρ‚ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ AQS ΠΈ встанСт Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ для пробуТдСния.

Богласно ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌΡƒ Π²Ρ‹ΡˆΠ΅ исходному ΠΊΠΎΠ΄Ρƒ Sync, ΠΌΡ‹ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ³Π΄Π° состояниС Π½Π΅ Ρ€Π°Π²Π½ΠΎ 0, tryAcquireShared() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ -1, Ρ‡Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ всС ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ await(), Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ поставлСны Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΊΠΎΠ³Π΄Π° счСтчик Π½Π΅ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π΄ΠΎ 0. .

ΠœΠ΅Ρ‚ΠΎΠ΄ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ отсчСта()

// java.util.concurrent.CountDownLatch.countDown()
public void countDown() {
    // 调用AQSηš„ι‡Šζ”Ύε…±δΊ«ι”ζ–Ήζ³•
    sync.releaseShared(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared()
public final boolean releaseShared(int arg) {
    // ε°θ―•ι‡Šζ”Ύε…±δΊ«ι”οΌŒε¦‚ζžœζˆεŠŸδΊ†οΌŒε°±ε”€ι†’ζŽ’ι˜Ÿηš„ηΊΏη¨‹
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

ΠœΠ΅Ρ‚ΠΎΠ΄ countDown() снимСт ΠΎΠ±Ρ‰ΡƒΡŽ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ количСство счСтчиков Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΎ Π½Π° 1.

Π’ соотвСтствии с Π²Ρ‹ΡˆΠ΅ΡƒΠΏΠΎΠΌΡΠ½ΡƒΡ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ синхронизации, ΠΌΡ‹ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ TRERELEasshared () Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ΄ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ количСство Ρ€Π°Π· ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ минус 1, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ True, ΠΊΠΎΠ³Π΄Π° Π΅Π³ΠΎ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π΄ΠΎ 0, Π½Π° этот Ρ€Π°Π· ΠΏΡ€ΠΎΠ±ΡƒΠ΄ΡƒΡ‚ ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ doReleaseShared() ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π°Π΅Ρ‚ ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π»ΠΈ Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ Π³Π»Π°Π²Π΅.

Π‘Π»ΡƒΡ‡Π°ΠΈ примСнСния

Π—Π΄Π΅ΡΡŒ ΠΌΡ‹ ΠΈΠΌΠΈΡ‚ΠΈΡ€ΡƒΠ΅ΠΌ сцСнарий использования, Ρƒ нас Π΅ΡΡ‚ΡŒ основной ΠΏΠΎΡ‚ΠΎΠΊ ΠΈ 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΆΠ΄Π΅ΠΌ готовности основного ΠΏΠΎΡ‚ΠΎΠΊΠ°, Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΆΠ΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ выполнСния 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², основной ΠΏΠΎΡ‚ΠΎΠΊ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ, ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π±Π»ΠΎΠΊ-схСма выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

CountDownLatch

Π”Π°Π²Π°ΠΉΡ‚Π΅ посмотрим, ΠΊΠ°ΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ написан этот ΠΊΠΎΠ΄:

public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(5);

        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                try {
                    System.out.println("Aid thread is waiting for starting.");
                    startSignal.await();
                    // do sth
                    System.out.println("Aid thread is doing something.");
                    doneSignal.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        // main thread do sth
        Thread.sleep(2000);
        System.out.println("Main thread is doing something.");
        startSignal.countDown();

        // main thread do sth else
        System.out.println("Main thread is waiting for aid threads finishing.");
        doneSignal.await();

        System.out.println("Main thread is doing something after all threads have finished.");

    }
}

Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ Π½Π° Π΄Π²Π΅ части:

ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ сСгмСнт, сигнал 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΡ… запуска, сигнал, испускаСмый основным ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ, Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ 5 ΠΌΠ΅Ρ‚ΠΎΠ΄ startSignal.await(), ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠΉ сигнала запуска, Π³Π»Π°Π²Π½ΠΎΠ΅, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΡ‚ΠΎΠΊ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ, Π²Ρ‹Π·ΠΎΠ² startSignal.countDown () Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ увСдомлСния ΠΎ Π½Π°Ρ‡Π°Π»Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹.

Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ Π°Π±Π·Π°Ρ†Π΅ основной ΠΏΠΎΡ‚ΠΎΠΊ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ сигнала Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², Π° сигнал выдаСтся 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, поэтому основной ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄ doneSignal.await() для оТидания сигнала Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° 5 Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‚ свою Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠœΠ΅Ρ‚ΠΎΠ΄ doneSignal.countDown() отправляСт собствСнный сигнал Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ, ΠΊΠΎΠ³Π΄Π° сигнал Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ достигаСт 5, ΠΎΠ½ ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π°Π΅Ρ‚ основной ΠΏΠΎΡ‚ΠΎΠΊ для продолТСния выполнСния ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ.

Π‘ΡƒΠΌΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ

(1) CountDownLatch ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΈΠ»ΠΈ нСскольким ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ ΠΆΠ΄Π°Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ;

(2) CountDownLatch Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ с использованиСм ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° ΠΎΠ±Ρ‰Π΅ΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ AQS;

(3) Когда CountDownLatch инициализируСтся, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ количСство отсчСтов;

(4) ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΌΠ΅Ρ‚ΠΎΠ΄Π° countDown() ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π½Π° 1;

(5) await () ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΊΠΎΠ³Π΄Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² попытаСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Π·Π°ΠΌΠΎΠΊ фактичСски приобрСтаСтся здСсь, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ AQS Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ 1;

(6) Когда Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ count (Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ состояния) ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡΡ Π΄ΠΎ 0, ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π΅Π½Ρ‹ (эти ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ await() для Π²Ρ…ΠΎΠ΄Π° Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ);

ΠΏΠ°ΡΡ…Π°Π»ΡŒΠ½Ρ‹Π΅ яйца

(1) МоТно Π»ΠΈ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ счСт CountDownLatch?

A: Когда ΠΌΡ‹ ΠΈΠ·ΡƒΡ‡Π°Π»ΠΈ Semaphore Ρ€Π°Π½ΡŒΡˆΠ΅, ΠΌΡ‹ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ врСмя Π΅Π³ΠΎ Π»ΠΈΡ†Π΅Π½Π·ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π² любоС врСмя.Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ врСмя CountDownLatch Π² любоС врСмя? ΠžΡ‚Π²Π΅Ρ‚ β€” Π½Π΅Ρ‚, ΠΎΠ½ Π½Π΅ Π΄Π°Π΅Ρ‚ возмоТности ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ (ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Ρ‚ΡŒ ΠΈΠ»ΠΈ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Ρ‚ΡŒ) количСство Ρ€Π°Π·, Π·Π° β€‹β€‹ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ использования отраТСния для ΠΎΠ±ΠΌΠ°Π½Π°.

(2) ΠŸΠΎΡ‡Π΅ΠΌΡƒ CountDownLatch ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ?

ΠžΡ‚Π²Π΅Ρ‚: ΠΌΡ‹ ΠΈΠ·ΡƒΡ‡ΠΈΠ»ΠΈ Ρ€Π΅ΠΆΠΈΠΌ раздСляСмой Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ AQS, ΠΊΠΎΠ³Π΄Π° Ρ€Π°Π½Π΅Π΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π»ΠΈ ReentrantReadWriteLock. НапримСр, тСкущая Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° приобрСтаСтся ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ ΠΊΠ°ΠΊ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡ, Ρ‚ΠΎΠ³Π΄Π° всС ΠΏΠΎΡ‚ΠΎΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΎΠ±Ρ‰ΡƒΡŽ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΠΏΠ°ΡΡ‚ΡŒ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ AQS для постановки Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. this Когда ΠΌΡŒΡŽΡ‚Π΅ΠΊΡ освобоТдаСтся, ΠΎΠ½ ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π°Π΅Ρ‚ эти Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠ΅ получСния ΠΎΠ±Ρ‰Π΅ΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΎΠ΄ΠΈΠ½ Π·Π° Π΄Ρ€ΡƒΠ³ΠΈΠΌ.ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Ρ‚Π΅Ρ€ΠΌΠΈΠ½ здСсь «пробуТдаСтся ΠΎΠ΄ΠΈΠ½ Π·Π° Π΄Ρ€ΡƒΠ³ΠΈΠΌΒ», Ρ‡Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ эти ΠΏΠΎΡ‚ΠΎΠΊΠΈ, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠ΅ получСния ΠΎΠ±Ρ‰Π΅ΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ΄Π½ΠΎΡ€Π°Π·ΠΎΠ²Ρ‹ΠΌ ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ.

ΠšΡΡ‚Π°Ρ‚ΠΈ говоря, Π²Ρ‹ ΠΏΠΎΠ½ΠΈΠΌΠ°Π΅Ρ‚Π΅? ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² CountDownLatch’s await() ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ нСсколько Ρ€Π°Π·, ΠΏΡ€ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ эти ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ AQS для постановки Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. .Если Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡ.ΠœΡŒΡŽΡ‚Π΅ΠΊΡΡ‹ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π²Π·Π°ΠΈΠΌΠΎΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΌΠΈ срСди Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΈ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π·Π±ΡƒΠΆΠ΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½.НСт Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ, Ρ‡Ρ‚ΠΎ, ΠΊΠΎΠ³Π΄Π° счСтчик ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡΡ Π΄ΠΎ 0, всС ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π²Ρ‹Π·Π²Π°Π²ΡˆΠΈΠ΅ ΠœΠ΅Ρ‚ΠΎΠ΄ оТидания() для оТидания Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π±ΡƒΠΆΠ΅Π½.

(3) Π’ Ρ‡Π΅ΠΌ Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ CountDownLatch ΠΈ Thread.join()?

ΠžΡ‚Π²Π΅Ρ‚: Thread.join() вызываСтся Π² основном ΠΏΠΎΡ‚ΠΎΠΊΠ΅. Он ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΡƒΠ²Π΅Π΄ΠΎΠΌΠ»ΡΡ‚ΡŒ основной ΠΏΠΎΡ‚ΠΎΠΊ, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ CountDownLatch отличаСтся. Π•Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ countDown() ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹Π·Π²Π°Π½ Π² любой ΠΌΠΎΠΌΠ΅Π½Ρ‚ выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠ°. ., большС гибкости.

Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌΠΎΠ΅ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅

1,ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ сСрии java-синхронизации ΠΌΠ΅Ρ€Ρ‚Π²Ρ‹Ρ… присСданий

2,НСбСзопасный Π°Π½Π°Π»ΠΈΠ· ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠ³ΠΎ магичСского класса Java

3.JMM (модСль памяти Java) ΠΈΠ· ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠΉ сСрии синхронизации Java

4.НСустойчивый Π°Π½Π°Π»ΠΈΠ· ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠΉ сСрии синхронизации Java

5.Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½Ρ‹ΠΉ Π°Π½Π°Π»ΠΈΠ· ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠΉ сСрии синхронизации Java

6.ΠΠ°ΠΏΠΈΡˆΠΈΡ‚Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Π² сСрии «Бинхронизация JavaΒ»

7.Начало AQS Π² сСрии синхронизации Java

8,ReentrantLock Π°Π½Π°Π»ΠΈΠ· исходного ΠΊΠΎΠ΄Π° Ρ‚ΡƒΠΏΠΈΠΊΠΎΠ²ΠΎΠΉ сСрии синхронизации Java (1) - справСдливая Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°, нСчСстная Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°

9,ReentrantLock Анализ исходного ΠΊΠΎΠ΄Π° ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠΉ сСрии синхронизации Java (2) β€” условная Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°

10.ReentrantLock VS синхронизирован Π² сСрии синхронизации java

11.Анализ исходного ΠΊΠΎΠ΄Π° ReentrantReadWriteLock ΠΌΠ΅Ρ€Ρ‚Π²ΠΎΠΉ сСрии синхронизации Java

12.Анализ исходного ΠΊΠΎΠ΄Π° сСмафора сСрии Dead Java Synchronization

Π”ΠΎΠ±Ρ€ΠΎ ΠΏΠΎΠΆΠ°Π»ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° мою ΠΎΠ±Ρ‰Π΅Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ ΡƒΡ‡Π΅Ρ‚Π½ΡƒΡŽ запись Β«Π‘Ρ€Π°Ρ‚ Π’ΠΎΠ½Π³ Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ исходный ΠΊΠΎΠ΄Β», ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ большС статСй ΠΈΠ· сСрии исходного ΠΊΠΎΠ΄Π° ΠΈ ΠΏΠΎΠΏΠ»Π°Π²Π°Ρ‚ΡŒ Π² ΠΎΠΊΠ΅Π°Π½Π΅ исходного ΠΊΠΎΠ΄Π° с Π±Ρ€Π°Ρ‚ΠΎΠΌ Π’ΠΎΠ½Π³ΠΎΠΌ.

qrcode