atomic_compare_exchange

atomic_compare_exchange (원자적 비교-교환)

atomic 객체의 값이 기대값과 같을 때만 원자적으로 새 값을 써 넣는 CAS(compare-and-swap) 연산이에요. 무잠금 동시성 자료구조의 핵심 연산이죠. 자유 함수 버전과 멤버 함수가 모두 있어요. <atomic> 헤더, C++11부터.

출처: cppreference

본문

atomic_compare_exchangeobj가 가리키는 값을 expected가 가리키는 값과 비교해요. 같으면 desired로 교체하고 true를, 다르면 obj의 현재 값을 *expected에 써 넣고 false를 반환해요. 즉 weak/strong 두 종류가 있어요.

template< class T >
bool atomic_compare_exchange_weak
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired ) noexcept;   // (1)

template< class T >
bool atomic_compare_exchange_strong
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired ) noexcept;   // (3)
  • weak: 성공 조건이 같더라도 거짓(false)으로 반환될 수 있어요(스퓨리어스 실패). 그래서 true가 나올 때까지 반복하는 CAS 루프에 적합해요. 빠르고 하드웨어에 친화적이에요.
  • strong: 값이 같으면 반드시 성공해요. 실패가 허용되지 않는 단일 호출에 적합해요.

_explicit 버전은 메모리 순서를 직접 지정해요. std::memory_ordersuccess/failure 두 개로 받아요. 자유 함수는 expected가 포인터(value_type*)라는 점, 멤버 함수(obj->compare_exchange_weak)는 참조로 받는다는 점이 차이예요.

_explicit 시그니처는 obj->compare_exchange_weak_explicit(expected, desired, success_order, failure_order) 형태예요.

전형적인 "같을 때만 갱신" 패턴을 무잠금으로 구현할 때 쓰여요. weak는 루프에서, strong은 원자적 단일 갱신이 보장되어야 할 때 쓰면 돼요.

더 알아보기 (Learn more)

cppreference