μˆ˜μ • 및 보완 ν•„μš” - Atomic Operation

μ›μžμ  μ—°μ‚°(Atomic Operation)

  • μž‘μ—…μ΄ 쀑간에 λŠκΈ°κ±°λ‚˜ λ°©ν•΄λ°›μ§€ μ•Šκ³  ν•œ λ²ˆμ— μ™„μ „ν•˜κ²Œ μˆ˜ν–‰λ˜λŠ” μ—°μ‚°μž…λ‹ˆλ‹€.
  • μ›μžμ  연산은 주둜 λ™μ‹œμ„±(Concurrency) 문제λ₯Ό λ°©μ§€ν•˜κ³ , 닀쀑 μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ 데이터 일관성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ©λ‹ˆλ‹€.

μ›μžμ  μ—°μ‚°μ˜ μ£Όμš” νŠΉμ§•

  1. λΉ„λΆ„ν• μ„±:
    • μ›μžμ  연산은 더 μž‘μ€ λ‹¨κ³„λ‘œ λ‚˜λˆ„μ–΄μ§€μ§€ μ•ŠλŠ” μ—°μ‚°μž…λ‹ˆλ‹€. 즉, 연산이 μ‹œμž‘λ˜λ©΄ 쀑간에 λ©ˆμΆ”κ±°λ‚˜ λ‹€λ₯Έ 연산이 끼어듀 수 μ—†μŠ΅λ‹ˆλ‹€.
    • 예λ₯Ό λ“€μ–΄, x++κ³Ό 같은 증가 연산이 μ›μžμ μ΄μ§€ μ•Šμ€ 경우, μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— x의 값을 λ³€κ²½ν•˜λ € ν•  λ•Œ 값이 꼬일 수 μžˆμŠ΅λ‹ˆλ‹€. μ›μžμ  연산을 μ‚¬μš©ν•˜λ©΄ x++κ°€ 쀑간에 λ°©ν•΄λ°›μ§€ μ•Šκ³  μ™„μ „ν•˜κ²Œ μ‹€ν–‰λ©λ‹ˆλ‹€.
  2. λ™μ‹œμ„± μ œμ–΄:
    • μ›μžμ  연산은 μ—¬λŸ¬ μŠ€λ ˆλ“œλ‚˜ ν”„λ‘œμ„ΈμŠ€κ°€ λ™μ‹œμ— λ™μΌν•œ 데이터λ₯Ό μˆ˜μ •ν•  λ•Œ λ°œμƒν•˜λŠ” 경쟁 쑰건(Race Condition)을 λ°©μ§€ν•©λ‹ˆλ‹€.
    • 이λ₯Ό 톡해 λ°μ΄ν„°μ˜ 무결성을 μœ μ§€ν•˜λ©°, 데이터가 μ˜ˆμƒμΉ˜ λͺ»ν•˜κ²Œ λ³€κ²½λ˜λŠ” 문제λ₯Ό ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μ„±λŠ₯ ν–₯상:
    • μ›μžμ  연산은 일반적으둜 락(Lock)보닀 λΉ λ₯΄λ©°, 적은 λΉ„μš©μœΌλ‘œ 동기화λ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • 닀쀑 μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ λ‹¨μˆœνžˆ 락을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  μ›μžμ  연산을 μ‚¬μš©ν•¨μœΌλ‘œμ¨, λΆˆν•„μš”ν•œ λŒ€κΈ° μ‹œκ°„μ„ 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

μ›μžμ  μ—°μ‚°μ˜ μ˜ˆμ‹œ

  1. 단일 CPU λͺ…λ Ήμ–΄λ‘œ μˆ˜ν–‰λ˜λŠ” μ—°μ‚°:
    • νŠΉμ • 연산은 단일 CPU λͺ…λ Ήμ–΄λ‘œ μˆ˜ν–‰λ  수 있으며, 이런 연산은 보톡 μ›μžμ μž…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, x = y처럼 값을 λ‹¨μˆœνžˆ λŒ€μž…ν•˜λŠ” 연산은 단일 CPU λͺ…λ Ήμ–΄λ‘œ 처리될 수 μžˆμŠ΅λ‹ˆλ‹€.
  2. CPU 지원 μ›μžμ  μ—°μ‚°:
    • CPUλŠ” λ™μ‹œμ„± μ œμ–΄λ₯Ό μœ„ν•œ μ›μžμ  연산을 μ§€μ›ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, Test-and-Set, Compare-and-Swapκ³Ό 같은 CPU λͺ…λ Ήμ–΄λ₯Ό 톡해 νŠΉμ • λ³€μˆ˜μ˜ 값을 μ›μžμ μœΌλ‘œ κ²€μ‚¬ν•˜κ³  μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. ν‘œμ€€ 라이브러리의 μ›μžμ  μ—°μ‚° ν•¨μˆ˜:
    • λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μ›μžμ  연산을 μœ„ν•œ λΌμ΄λΈŒλŸ¬λ¦¬λ‚˜ λͺ…λ Ήμ–΄λ₯Ό μ œκ³΅ν•˜λ©°, 이λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‰½κ²Œ μ›μžμ  연산을 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • 예λ₯Ό λ“€μ–΄, C++μ—μ„œλŠ” std::atomic 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ μ›μžμ  λ³€μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. std::atomic<int> x와 같은 λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λ©΄ x++, x-- 연산이 μ›μžμ μœΌλ‘œ μˆ˜ν–‰λ©λ‹ˆλ‹€.

μ›μžμ  μ—°μ‚°μ˜ μ‚¬μš© μ˜ˆμ‹œ

#include <atomic>
#include <iostream>
#include <thread>

std::atomic<int> counter(0);  // μ›μžμ  λ³€μˆ˜ μ„ μ–Έ

void increment() {
    for (int i = 0; i < 1000; ++i) {
        counter++;  // μ›μžμ  증가 μ—°μ‚°
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Counter: " << counter << std::endl;
    return 0;
}

μœ„ μ˜ˆμ œμ—μ„œ counter++λŠ” μ›μžμ  μ—°μ‚°μœΌλ‘œ μˆ˜ν–‰λ˜μ–΄, μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— counter λ³€μˆ˜λ₯Ό μˆ˜μ •ν•˜λ”λΌλ„ λ°μ΄ν„°μ˜ 일관성이 μœ μ§€λ©λ‹ˆλ‹€.

μ›μžμ  연산이 ν•„μš”ν•œ 이유

  1. 경쟁 쑰건 λ°©μ§€:
    • μ›μžμ  연산은 μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 같은 데이터λ₯Ό μˆ˜μ •ν•  λ•Œ λ°œμƒν•˜λŠ” 경쟁 쑰건을 λ°©μ§€ν•©λ‹ˆλ‹€.
  2. 데이터 일관성 보μž₯:
    • μ›μžμ  연산을 μ‚¬μš©ν•˜λ©΄, 연산이 μ™„λ£Œλ˜κΈ° μ „κΉŒμ§€λŠ” λ‹€λ₯Έ 연산이 끼어듀 수 μ—†κΈ° λ•Œλ¬Έμ—, 데이터가 μ˜ˆμƒμΉ˜ λͺ»ν•˜κ²Œ λ³€κ²½λ˜λŠ” 상황을 λ°©μ§€ν•˜κ³  λ°μ΄ν„°μ˜ 일관성을 보μž₯ν•©λ‹ˆλ‹€.
  3. λ°λ“œλ½ νšŒν”Ό:
    • μ›μžμ  연산은 락을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  동기화가 ν•„μš”ν•œ λΆ€λΆ„λ§Œ μ›μžμ μœΌλ‘œ μ²˜λ¦¬ν•˜κΈ° λ•Œλ¬Έμ—, λ°λ“œλ½μ„ νšŒν”Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ›μžμ  μ—°μ‚°μ˜ ν•œκ³„

  • μ›μžμ  연산은 단일 λ³€μˆ˜μ— λŒ€ν•΄ μ›μžμ„±μ„ 보μž₯ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ—¬λŸ¬ λ³€μˆ˜ κ°„μ˜ λ³΅μž‘ν•œ μ—°μ‚°μ—μ„œλŠ” 데이터 일관성을 μ™„λ²½νžˆ 보μž₯ν•˜μ§€ λͺ»ν•  수 있으며, μ΄λ•ŒλŠ” 일반적으둜 락을 μ‚¬μš©ν•œ 동기화가 ν•„μš”ν•©λ‹ˆλ‹€.

μš”μ•½

μ›μžμ  연산은 쀑간에 λ°©ν•΄λ°›μ§€ μ•Šκ³  ν•œ λ²ˆμ— μˆ˜ν–‰λ˜λŠ” μ—°μ‚°μœΌλ‘œ, λ™μ‹œμ„± μ œμ–΄μ™€ 데이터 일관성을 μœ μ§€ν•˜λŠ” 데 μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. μ›μžμ  연산을 μ‚¬μš©ν•˜λ©΄, 닀쀑 μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ λ°μ΄ν„°μ˜ μΆ©λŒμ„ λ°©μ§€ν•˜μ—¬ μ•ˆμ •μ μ΄κ³  효율적인 ν”„λ‘œκ·Έλž¨μ„ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν—€λ”νŒŒμΌλ‘œ 제곡