AtomicLong๋ž€

  • ์ž๋ฐ”์—์„œ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค๋กœ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์›์ž์ ์œผ๋กœ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.
  • java.util.concurrent.atomic ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณต์„ ํ•˜๋ฉฐ, AtomicInteger, AtomicBoolean, AtomiceReference ๋“ฑ ๋‹ค๋ฅธ ์ž๋ฃŒํ˜•์— ๋Œ€ํ•ด์„œ๋„ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • Atomic , ์›์ž๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๊ฐ ์—ฐ์‚ฐ์„ ์™ธ๋ถ€์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๊ณ  ์›์ž์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • lock์„ ๊ฑธ์ง€ ์•Š๊ณ  ๋™์‹œ์„ฑ ํ™˜๊ฒฝ์„ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•œ CAS ์—ฐ์‚ฐ์„ ์ ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.
    • AtomicLong์™€ ๊ฐ™์€ ํด๋ž˜์Šค์—๋„ ํ•ด๋‹น ์—ฐ์‚ฐ์ด ์ ์šฉ๋๋‹ค๊ณ  ํ•œ๋‹ค.

์ฆ๊ฐ์—ฐ์‚ฐ์ž์™€ ์ฐจ์ด์ 

  • userId++๊ณผ ๊ฐ™์€ ์ฆ๊ฐ ์—ฐ์‚ฐ์ž๋Š” ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€๋งŒ, ์ ์  ์Šค๋ ˆ๋“œ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๊ธฐ๋Œ€ํ•œ ๊ฐ’์„ ํ™•์ธํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค.
  • ๊ทธ ์ด์œ ๋Š” ++ ์™€ ๊ฐ™์€ ์ฆ๊ฐ์—ฐ์‚ฐ์˜ ๋กœ์ง ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ•œ๋‹ค.
    • userId์˜ ๊ฐ’์„ ์–ป๋Š”๋‹ค.
    • userId์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
    • ์ฆ๊ฐ€๋œ userId์˜ ๊ฐ’์„ ๊ธฐ์กด ๋ฉ”๋ชจ๋ฆฌ์— ๋‹ค์‹œ ์“ด๋‹ค.
  • ๋งŒ์•ฝ, ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—์„œ userId++ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋˜๋ฉด, ์ดˆ๊ธฐ์— ๋™์ผํ•œ ๊ฐ’์„ ์–ป๊ณ  ๊ฐ๊ฐ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋Œ€๊ฐ’๋ณด๋‹ค ์ ๊ฒŒ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • A์™€ B๊ฐ€ userId = 6์˜ ๊ฐ’์„ ์ฆ๊ฐ์—ฐ์‚ฐ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ฌ๋ ค๊ณ  ํ•œ๋‹ค.
    • ์ดˆ๊ธฐ์— ๋™์ผํ•œ ๊ฐ’ 6์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๊ณ  ๊ฐ๊ฐ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
    • ๊ทธ๋Ÿฌ๋ฉด A์™€ B๋Š” ๋™์ผํ•˜๊ฒŒ 7์ด๋ผ๋Š” ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.
    • A์™€ B๊ฐ€ ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผฐ๊ธฐ ๋•Œ๋ฌธ์— userId๋Š” 8์ด๋ผ๋Š” ๊ฐ’์„ ๊ฐ€์ ธ์•ผํ•˜์ง€๋งŒ, ๊ฒฐ๊ณผ์ ์œผ๋กœ๋Š” 7์ด๋ผ๋Š” ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋๋‹ค.
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์กด์žฌํ•œ๋‹ค.
    • ๋‹ค๋งŒ ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ lock๋ฅผ ๊ฑธ๊ณ  ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” lock์ด ํ’€๋ฆด ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ฌ๋ ค์•ผ ํ•œ๋‹ค.
    • ๋‹ค๋ฅธ ์ผ์„ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ๊ณ„์† ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ…Œ์ŠคํŠธ

@Test
void addTest() throws InterruptedException {
    Counter counter = new Counter();
    int threadCount = 10000;

    ExecutorService executorService = Executors.newFixedThreadPool(32);
    CountDownLatch countDownLatch = new CountDownLatch(threadCount);

    for (int i = 0; i < threadCount; i++) {
        executorService.submit(() - > {
            try {
                counter.increment();
            } finally {
                countDownLatch.countDown();
            }
        });
    }
    countDownLatch.await();
    executorService.shutdown();

    assertEquals(threadCount, counter.getCount());
}

public static class Counter {
    int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}
  • int ์ž๋ฃŒํ˜•์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ๋ ค ํ–ˆ์œผ๋‚˜, ์Šค๋ ˆ๋“œ๊ฐ„ ๊ณต์œ ๊ฐ€ ๋˜์ง€ ์•Š์•„ Atomic ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ๋‚˜์™”๋‹ค.
  • ์ˆœ์ˆ˜ ์ฆ๊ฐ ์—ฐ์‚ฐ์ž๋งŒ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์—, Counter๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์„ ์–ธํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

-   ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ ์„ ๋•Œ๋Š” ํ†ต๊ณผ๋ฅผ ํ•˜์ง€๋งŒ, ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๋ฉด ์ ์  ๊ธฐ๋Œ“๊ฐ’๋ณด๋‹ค ์ ์€ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
public synchronized void increment() {
    count++;
}
  • synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ดค๋‹ค.
  • ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

-   ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹คํ–‰์‹œ๊ฐ„์—์„œ ํฐ ์ฐจ์ด๊ฐ€ ๋‚˜์ง€ ์•Š์•˜๋‹ค.
-   ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž˜๋ชป ์ž‘์„ฑํ•œ๊ฑด๊ฐ€..?