Item 81. Concurrent Utilities

wait와 notifyλ³΄λ‹€λŠ” λ™μ‹œμ„± μœ ν‹Έλ¦¬ν‹°λ₯Ό μ• μš©ν•˜λΌ

wait와 notiyλŠ” κ³ μˆ˜μ€€μ˜ λ™μ‹œμ„± μœ ν‹Έλ¦¬ν‹°κ°€ μ§€μ›ν•˜κΈ° 이전엔 잘 μ•Œμ•„λ‘¬μ•Ό ν–ˆμ§€λ§Œ, μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•˜κΈ° κΉŒλ‹€λ‘­κ³  λ™μ‹œμ„± μœ ν‹Έλ¦¬ν‹°κ°€ μ§€μ›ν•˜λŠ” ν˜„ μ‹œμ μ—μ„œλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€.(μœ ν‹Έλ¦¬ν‹° μ‚¬μš© ꢌμž₯) java.util.concurrent νŒ¨ν‚€μ§€μ—μ„œ μ œκ³΅ν•˜λŠ” κ³ μˆ˜μ€€ μœ ν‹Έλ¦¬ν‹°λŠ” μ„Έ 가지 λ²”μ£Όλ‘œ λ‚˜λˆŒ 수 μžˆλ‹€.

  • μ‹€ν–‰μž ν”„λ ˆμž„μ›Œν¬: μž‘μ—…μ„ λΉ„λ™κΈ°μ μœΌλ‘œ μ‹€ν–‰ν•  수 있게 ν•΄μ€€λ‹€.(ExecutorService μΈν„°νŽ˜μ΄μŠ€μ™€ ThreadPoolExecutor 클래슀λ₯Ό ν¬ν•¨ν•œ ν”„λ ˆμž„μ›Œν¬)

  • λ™μ‹œμ„± μ»¬λ ‰μ…˜: λ™μ‹œμ„±μ„ μ§€μ›ν•˜λŠ” μ»¬λ ‰μ…˜μ„ μ œκ³΅ν•œλ‹€.(ConcurrentHashMap, CopyOnWriteArrayList λ“±)

    • λ‚΄λΆ€μ—μ„œ 동기화λ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— λ™μ‹œμ„±μ„ 무λ ₯ν™”ν•˜λŠ” 것은 λΆˆκ°€λŠ₯ν•˜κ³ , μ™ΈλΆ€ 락을 μΆ”κ°€λ‘œ μ‚¬μš©ν•˜λ©΄ μ„±λŠ₯이 μ €ν•˜λœλ‹€.

    • μ—¬λŸ¬ λ©”μ„œλ“œλ₯Ό μ›μžμ μœΌλ‘œ λ¬Άμ–΄ ν˜ΈμΆœν•˜λŠ” 것이 λΆˆκ°€λŠ₯ν•˜λ‹€.

    • λ•Œλ¬Έμ— μ—¬λŸ¬ κΈ°λ³Έ λ™μž‘μ„ ν•˜λ‚˜μ˜ λ™μž‘μœΌλ‘œ λ¬ΆλŠ” μƒνƒœ 의쑴적 μˆ˜μ • λ©”μ„œλ“œλ“€μ΄ 좔가됬어닀.(λ™μ‹œμ„± μ»¬λ ‰μ…˜ 뿐만 μ•„λ‹ˆλΌ 일반 μ»¬λ ‰μ…˜μ—μ„œλ„ μ‚¬μš© κ°€λŠ₯)

  • 동기화 μž₯치: μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œλ₯Ό 기닀릴 수 있게 ν•˜μ—¬, μž‘μ—…μ„ μ‘°μœ¨ν•  수 있게 ν•΄μ€€λ‹€.(CountDownLatch, Semaphore, Phaser λ“±)

동기화 μž₯치λ₯Ό μ‚¬μš©ν•œ μ˜ˆμ‹œ

동기화 μž₯치λ₯Ό μ‚¬μš©ν•˜λ©΄, wait, notifyλ₯Ό μ΄μš©ν•˜λŠ” 것보닀 더 κ°„λ‹¨ν•˜κ²Œ λ™μ‹œμ„±μ„ λ‹€λ£° 수 μžˆλ‹€. μ•„λž˜μ˜ μ˜ˆμ‹œλŠ” CountDownLatchλ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μž‘λ“€μ„ λ™μ‹œμ— μ‹œμž‘ν•΄ λͺ¨λ‘ μ™„λ£Œν•˜λŠ” 데 κ±Έλ¦¬λŠ” μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” λ©”μ„œλ“œμ΄λ‹€.

import java.util.concurrent.CountDownLatch;

public class Test {

    // λ™μž‘λ“€μ„ λ™μ‹œμ— μ‹œμž‘ν•΄ λͺ¨λ‘ μ™„λ£Œν•˜λŠ” 데 κ±Έλ¦¬λŠ” μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” λ©”μ„œλ“œ
    public static long time(Executor executor, int concurrency, Runnable action)
            throws InterruptedException {
        CountDownLatch ready = new CountDownLatch(concurrency);
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch done = new CountDownLatch(concurrency);

        for (int i = 0; i < concurrency; i++) {
            // concurrency만큼 μž‘μ—…μž μŠ€λ ˆλ“œλ₯Ό 생성
            executor.execute(() -> {
                // 타이머에 μ€€λΉ„ μ™„λ£Œ μ‹ ν˜Έλ₯Ό 보냄
                ready.countDown();
                try {
                    // λͺ¨λ“  μž‘μ—…μž μŠ€λ ˆλ“œκ°€ 쀀비될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
                    start.await();
                    action.run();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    // 타이머에 μž‘μ—… μ™„λ£Œ μ‹ ν˜Έλ₯Ό 보냄
                    done.countDown();
                }
            });
        }

        ready.await(); // λͺ¨λ“  μž‘μ—…μžκ°€ 쀀비될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
        long startNanos = System.nanoTime();
        start.countDown(); // μž‘μ—…μžλ“€μ„ 깨움
        done.await(); // λͺ¨λ“  μž‘μ—…μžκ°€ μž‘μ—…μ„ μ™„λ£Œν•  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
        return System.nanoTime() - startNanos;
        // nanoTime이 currentTimesMillis보닀 더 μ •ν™•ν•˜κ³ , μ‹œμŠ€ν…œμ˜ μ‹€μ‹œκ°„ μ‹œκ³„ μ‹œκ°„ 보정에 영ν–₯을 받지 μ•ŠμŒ
    }
}

μ½”λ“œμ˜ 흐름은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. ready.countDown()둜 μž‘μ—…μž μŠ€λ ˆλ“œκ°€ 쀀비됨을 μ•Œλ¦Ό

  2. start.await()둜 λͺ¨λ“  μž‘μ—…μž μŠ€λ ˆλ“œκ°€ 쀀비될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό(start.countDown()을 λŒ€κΈ°)

  3. read.await()둜 λͺ¨λ“  μž‘μ—…μž μŠ€λ ˆλ“œκ°€ 쀀비될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό

  4. done.countDown()으둜 2λ²ˆμ—μ„œ λŒ€κΈ°ν•œ μž‘μ—…μž μŠ€λ ˆλ“œλ₯Ό 깨움

  5. done.await()둜 λͺ¨λ“  μž‘μ—…μž μŠ€λ ˆλ“œκ°€ μž‘μ—…μ„ μ™„λ£Œν•  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό

  6. action.run()으둜 μž‘μ—…μ„ μˆ˜ν–‰

  7. done.countDown()으둜 μž‘μ—…μ„ μ™„λ£Œν•¨μ„ μ•Œλ¦Ό

  8. λͺ¨λ“  μž‘μ—…μ΄ μ™„λ£Œλ˜μ–΄ done.await()κ°€ 풀리면 System.nanoTime() - startNanosλ₯Ό λ°˜ν™˜

wait와 notify

wait와 notifyλŠ” κ³ μˆ˜μ€€ λ™μ‹œμ„±μ„ μ‚¬μš©ν•  수 μžˆλŠ” 상황에선 μ „ν˜€ κ³ λ €ν•  ν•„μš”κ°€ μ—†μœΌλ©°, λ§Œμ•½ λ ˆκ±°μ‹œ μ½”λ“œλ₯Ό 닀뀄야 ν•œλ‹€λ©΄, μ•„λž˜μ˜ κ·œμΉ™μ„ λ”°λ₯΄κ³  μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•˜λŠ” 방법을 μ•Œμ•„λ‘λŠ” 것이 μ’‹λ‹€.

  • waitλŠ” λ°˜λ“œμ‹œ λŒ€κΈ° 반볡문(while 루프 μ‚¬μš©) μ•ˆμ—μ„œ ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.

  • 일반적으둜 notifyλ³΄λ‹€λŠ” notifyAll을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

Last updated

Was this helpful?