IT/JAVA

동기화 vs 원자적 연산

iamhyeon 2025. 7. 24. 16:31

 

멀티스레드 환경에서 데이터 일관성과 충돌 방지는 반드시 고려해야 할 중요한 주제이다.
동기화(synchronization)와 원자적 연산(atomic operation)은 모두 이를 다루는 방법이지만, 그 목적과 동작 방식이 다르다.

 

동기화 (Synchronization)

  • 공유 자원(변수, 객체, 컬렉션 등)에 여러 스레드가 동시 접근할 때 충돌을 막기 위한 보장 수단
  • Java에서는 synchronized 키워드 또는 Lock 인터페이스를 통해 구현

✅ 예시

class Counter {
  private int count = 0;

  public synchronized void increment() {
    count++;
  }
}

이 코드에서는 increment() 메서드 전체가 임계 구역(critical section)으로 보호되어, 여러 스레드가 한 번에 실행할 수 없다.

 

장점 vs 단점

  • ✔️ 완전한 보호: 임계 구역 전체가 스레드 안전
  • 병목 발생 가능: 전체 메서드 동기화 시, 동시 처리 성능 저하

 

원자적 연산 (Atomic Operation)

  • 단일 연산 단위로, 중간 중단이나 간섭 없이 실행되는 연산
  • Java에서는 AtomicInteger, AtomicReference, AtomicBoolean 등 java.util.concurrent.atomic 패키지 제공

 

✅ 예시

import java.util.concurrent.atomic.AtomicInteger;

AtomicInteger atomicCount = new AtomicInteger(0);
atomicCount.incrementAndGet(); // 원자적 증가

이 코드에서 incrementAndGet()은 읽기+증가+저장하나의 연산 단위로 보장한다.

 

장점 vs 단점

  • Lock-free: synchronized 없이도 안전하게 동작
  • 성능 우수: 자주 호출되어도 병목이 적다
  • 복합 연산에는 부적합: compare-then-act 등 여러 단계일 경우에도 별도 처리 필요하다

 

동기화 vs 원자적 연산 비교

  동기화 (synchronized / Lock) 원자적 연산 (Atomic*)
보호 단위 임계 구역 (메서드/블록) 하나의 변수 연산
성능 락 경합 시 잠금 발생 가능 비차단 → 스루풋 좋음
복합 연산 increment() 같은 경우 모두 보호 가능 위험, CAS 실패 시 재시도 필요
구현 복잡도 간단하지만 과도 사용 시 성능 저하 단일 변수 연산에 적합

 

  • 단순한 증가/읽기처럼 변수를 원자적으로 다루고 싶다면:
    → AtomicInteger, AtomicLong 추천
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();
  • 여러 변수를 같이 보호하거나 복잡한 로직이 있을 때는:
    → synchronized 또는 ReentrantLock 사용
synchronized(this) {
  x += 1;
  y += 2;
}

 

  • Atomic 연산은 단일 변수에 대해서만 원자적이며, 여러 변수나 조건부 업데이트는 동기화 필요
  • synchronized는 과도하게 사용 시 성능 병목 우려 → 임계 구역을 좁게 유지

 

 

개념  보호 단위  성능  적합 사례
동기화 여러 라인/메서드 락 경합 시 느림 복합 로직, 여러 공유 자원
원자적 연산 단일 변수 Lock-free 빠름 증가, 플래그 변경 등 단순 작업

 

 

  • 동기화(synchronized)는 복잡한 상태와 여러 작업 보호에 적합하지만 성능 부담이 있을 수 있다.
  • Atomic*는 단일 변수의 안전한 증가/읽기를 고성능으로 처리할 수 있어 현대 Java에서 가장 널리 사용되는 기법이다.

 

반응형