Java) Volatile / Synchronized / Atomic

박동규·2023년 5월 18일
0

일반적으로 Java 멀티쓰레드 환경에서 동기화문제는 synchronzied, Atomic, volatile 세가지 키워드로 해결한다.

Volatile

  • volatile 는 변수를 메인메모리에 저장한다고 명시하는 것이다.
  • 변수의 값을 읽을 땐, CPU 캐시에 저장된 값이 아닌 메인메모리에서 읽어온다.
  • 변수의 값을 저장할 땐, 메인메모리에 저장한다.

오직 1개의 쓰레드에서 저장 작업을 하고 다른 쓰레드는 조회만 할 때 안정성이 보장되는 방법이다.

-- 23.07.14 내용 추가

1개의 쓰레드에서만 저장 작업을 할 때 안정성이 보장된다는 것이 무슨 뜻일까?

공유 자원에 동기화 문제가 발생하는 것은 Main memory에 있는 공유 자원에 동시 접근한 상황에

write를 수행하는 쓰레드가 CPU 레지스터에 새로 write할 변수의 값을 계산하여 가지고 있고,

다른 쓰레드에서 공유 자원을 read 할 때 가장 최신의 값인 CPU 레지스터의 값을 읽지 않고 Main memory의 값을 읽기 때문에 발생하는 동기화 문제이다.

Volatile 키워드는 이러한 변수의 '가시성' 문제를 해결할 뿐이다.

Volatile 키워드를 사용 하더라도 여러 쓰레드에서 동시에 write 작업이 일어나 Main memory에 저장을 시도한다면 공용 자원이 덮어 씌워지는 문제는 여전히 존재한다는 뜻이다.

즉, Volatile 키워드로 가시성 문제 는 해결할 수 있으나 동시접근 문제 는 해결할 수 없다는 의미

Synchronized

  • synchronized 는 접근한 쓰레드가 해당 블럭 전체를 Lock을 걸기 때문에
    다른 쓰레드는 Block 상태에 걸려 먼저 접근한 쓰레드가 작업이 완료될 때까지 대기하게 된다.

Atomic

  • Synchronized 의 자원 낭비를 해결하기 위해 NonBlocking 방식으로 동기화 문제를 해결한 방법이다.
  • Atomic 은 원자성을 보장한다.
  • Atomic 의 핵심 동작 원리는 CAS 알고리즘 이다.(Compared and Swap)

하나의 변수에 2개의 쓰레드가 찰나의 시간 차이로 동시 접근할 때,
조금이라도 먼저 변수값을 수정한 쓰레드가 존재할 것이다.

이 때 변수값을 수정하면 CPU캐시에 저장된 값이 변경되고,
메인 메모리에 저장된 값은 아직 반영되지 않은 상태이고
이러한 경우 먼저 접근한 쓰레드가 자원을 사용 중이라 판단하고 동작하는 것이다.

즉, 자원에 접근하는 쓰레드는 CPU 캐시에 저장된 값과 메인 메모리에 저장된 값을 비교한 뒤
값이 같지 않다면, 자신의 값을 처리하지 않는다.
false가 반환된 경우 무한 루프를 통해 값을 비교한 뒤, 자신의 값을 반영하는 방식으로 동시성 문제를 해결한다.

참고 : https://beomseok95.tistory.com/225 |
https://zion830.tistory.com/58 |
https://perenok.github.io/Atomic-Type/ |
https://velog.io/@xylopeofficial/asynchronized-%EC%99%80-volatile-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Atomic

0개의 댓글