서버 개발/멀티쓰레드 프로그래밍

ABA 문제와 사례

지노윈 2025. 9. 18. 11:15
반응형

ABA 문제란?

  • 어떤 스레드가 변수의 값을 A라고 확인하고, 나중에 그 값이 여전히 A라서 안전하다고 착각해 연산을 진행했는데…
  • 사실은 그 사이에 다른 스레드가 A → B → A로 바꿔치기한 경우 발생하는 문제.
  • 즉, 값은 다시 A라서 “겉보기엔 변화 없음”처럼 보이지만, 실제로는 상태가 바뀌었고 의도하지 않은 결과가 생김.

 

Lock-Free Stack (스택 pop/push)

struct Node {
    int data;
    Node* next;
};

std::atomic<Node*> head;
 
  • Thread T1 (Pop)
    1. head를 읽음 → Node A 가리킴
    2. A->next를 확인 → Node B
    3. CAS로 head를 A에서 B로 바꾸려 함
  • Thread T2 (Pop+Push)
    1. T1이 CAS하기 전에 실행
    2. A를 pop → head는 B
    3. B도 pop → head는 C
    4. 다시 A를 push → head는 A
  • T1 시점으로 돌아가서
    • head는 여전히 A → CAS 성공
    • 하지만 실제 head는 이미 A → pop → push 과정을 거친, 완전히 다른 상태

➡ 결과적으로 스택 구조가 꼬이거나, 이미 해제된 노드(A)에 접근하는 문제가 발생

 

Lock-Free Queue

  • 큐의 head 포인터를 CAS로 업데이트할 때,
  • 다른 스레드가 head 노드를 dequeue했다가 다시 recycle해서 enqueue → 다시 head에 등장
  • CAS는 값이 여전히 동일하다고 판단 → 잘못된 링크 구조 발생

메모리 풀 / 오브젝트 재사용

  • 메모리 관리에서 free list를 CAS 기반으로 업데이트할 때
  • 이미 free된 노드가 다른 스레드에서 재할당 → 같은 주소지만 의미가 다른 객체가 됨
  • CAS는 주소가 같으니 성공 → 잘못된 메모리 조작

왜 위험한가?

  • CAS는 단순히 "값이 같은지 여부"만 확인하기 때문에, 값이 동일해도 그 사이의 변화를 감지하지 못함
  • 결과적으로 메모리 안전성 문제(Use-after-free, Double-free)나 데이터 구조 불일치가 발생

 

반응형