Item 81. Concurrent Utilities

wait์™€ notify๋ณด๋‹ค๋Š” ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์• ์šฉํ•˜๋ผ

wait์™€ notiy๋Š” ๊ณ ์ˆ˜์ค€์˜ ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์ง€์›ํ•˜๊ธฐ ์•„์ „์—” ์ž˜ ์•Œ์•„๋‘ฌ์•ผ ํ–ˆ์ง€๋งŒ, ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šด ๊ธฐ๋Šฅ์œผ๋กœ, ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์ง€์›ํ•˜๋Š” ํ˜„ ์‹œ์ ์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.(์œ ํ‹ธ๋ฆฌํ‹ฐ ์‚ฌ์šฉ ๊ถŒ์žฅ)

java.util.concurrent ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ณ ์ˆ˜์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ์„ธ ๊ฐ€์ง€ ๋ฒ”์ฃผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  • ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ: ์ž‘์—…์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.(ExecutorService ์ธํ„ฐํŽ˜์ด์Šค์™€ ThreadPoolExecutor ํด๋ž˜์Šค๋ฅผ ํฌํ•จํ•œ ํ”„๋ ˆ์ž„์›Œํฌ)

  • ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜: ๋™์‹œ์„ฑ์„ ์ง€์›ํ•˜๋Š” ์ปฌ๋ ‰์…˜์„ ์ œ๊ณตํ•œ๋‹ค.(ConcurrentHashMap, CopyOnWriteArrayList ๋“ฑ)

    • ๋‚ด๋ถ€์—์„œ ๋™๊ธฐํ™”๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ์„ฑ์„ ๋ฌด๋ ฅํ™”ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ์™ธ๋ถ€ ๋ฝ์„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค.

    • ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์›์ž์ ์œผ๋กœ ๋ฌถ์–ด ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

    • ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๊ธฐ๋ณธ ๋™์ž‘์„ ํ•˜๋‚˜์˜ ๋™์ž‘์œผ๋กœ ๋ฌถ๋Š” ์ƒํƒœ ์˜์กด์  ์ˆ˜์ • ๋ฉ”์„œ๋“œ๋“ค์ด ์ถ”๊ฐ€๋ฌ์–ด๋‹ค.(๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜ ์ปฌ๋ ‰์…˜์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ)

  • ๋™๊ธฐํ™” ์žฅ์น˜: ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ฅผ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์—ฌ, ์ž‘์—…์„ ์กฐ์œจํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.(CountDownLatch, Semaphore, Phaser ๋“ฑ)

๋™๊ธฐํ™” ์žฅ์น˜๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ

๋™๊ธฐํ™” ์žฅ์น˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, wait, notify๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋™์‹œ์„ฑ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ๋Š” 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