Java Atomic 자료형의 작동 방식

이상민·2021년 8월 6일
0
post-thumbnail

1. Atomic 객체

이전에 동기화 관련 공부를 하면서 자바에선 Atomic 자료형들이 thread-safe한 작업을 보장해준다는 것과, 하드웨어 레벨 instruction으로 test_and_set(), compare_and_swap() 같은 것들이 있다는 것을 배웠다. 이번에 간단하게 AtomicInteger를 사용해 getAndIncrement()해야하는 상황이 있었는데, 실제로 이 자료형의 메소드들이 어떻게 작동하는지 궁금해 찾아봤다.


2. Atomic 객체의 작동방식

  • 자바의 atomic 객체들은 compare_and_swap() 메커니즘을 사용해 원자성을 보장한다
// compare_and_swap()의 pseudo code
function compare_and_swap(p: pointer to int, old: int, new: int) is
    if *p ≠ old
        return false

    *p ← new

    return true
  • compare_and_swap()이 어떤 로직으로 작동하는지는 이해했지만, 어떻게 hw instruction level에서 atomic하게 작동하는지는 이해 못했다 @_@ 캐쉬가 어쩌고 하던데 나중에 다시 찾아봐야겠다

  • 원자성을 만족하는 compare_and_swap() 덕분에 경쟁 상태에서도 문제 없이 하나의 스레드만 increment가 가능하다

  • 아래는 AtomicInteger 클래스로 가면 볼 수 있는 코드이다.

    public final int getAndIncrement() {
        return U.getAndAddInt(this, VALUE, 1);
    }

3. 연산 실패

  • compare_and_swap() 명령어에 따라 동시에 여러 스레드가 연산을 시도하면, 하나의 스레드만 increment를 성공하고 나머지는 실패할 것이다

  • 이때문에 Atomic 객체에서는 성공할때까지 while 루프를 돈다

public final int getAndAddInt(Object o, long offset, int delta) {
    int v;
    do {
        v = this.getIntVolatile(o, offset);
    } while(!this.weakCompareAndSetInt(o, offset, v, v + delta));

    return v;
}
  • 자바에서 volatile 관련 키워드는 CPU 캐쉬가 아닌 메인 메모리에 작업하겠다는 키워드이다

  • compare_and_swap() 같은 명령어 중에서 결과 값을 int가 아닌 boolean으로 반환하는 명령어를 compare_and_set()이라고 한다


참고

https://en.wikipedia.org/wiki/Compare-and-swap
https://stackoverflow.com/questions/56216323/how-does-atomicinteger-is-thread-safe

profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

0개의 댓글

관련 채용 정보