Atomic, Volatile, Synchronized 이 세 가지는 다중 스레드 환경에서 동시성을 제어하기 위해 사용하는 키워드와 클래스이다.
우선, 동기화에는 두 가지 기능이 있다.
첫 번째는 원자성을 보장하는 배타적 실행,
두 번째는 한 스레드가 만든 변화를 다른 스레드에서 확인할 수 있는 가시성이다.
Synchronized는 메서드나 블록을 한번에 한 스레드만 수행하도록 보장하는 배타적 실행의 기능을 한다.
volatile은 변수 앞에 붙이게 되면 캐싱된 데이터가 아닌, 메모리에서 값을 직접 읽고 쓰게 된다. 따라서 가장 최근에 기록된 값을 읽는 것을 보장하고, 변수의 가시성을 보장한다고 볼 수 있다. (lock-free 하기 때문에 성능면에도 좋다)
Atomic은 lock-free하면서 thread-safe한 기능을 지원하는 클래스이다. CAS알고리즘을 사용하여 기존 값과 현재 메모리가 가지고 있는 값을 비교한 뒤, 같다면 값을 변경하고, 다르다면 변경하지 않는 방식을 사용한다.
🌟 추가 질문
📍 Atomic의 종류와 어떤 상황에서 사용하면 좋을까?
AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference<\T>, AtomicStampedReference<\T>, AtomicMarkableReference<\T> 등 존재한다.
Atomic은 락을 사용하지 않고도 변수의 원자적 연산을 제공하는 방식으로, 성능과 동시성을 동시에 보장하는 특성이 있다.
주로 스레드 간 카운터 동기화에 자주 사용이 되며, 여러 스레드가 동시에 숫자를 읽고, 증가시키거나 감소시켜야 할 때 자주 사용된다. 예시로, 동시 접속자 수를 카운팅하거나, 고유한 ID를 생성하는 작업에서 락을 사용하지 않고도 안전하게 값을 처리할 수 있다.
📍 volatile 사용 이유와 주로 쓰이는 상황?
volatile은 가시성은 보장하지만 원자성은 보장하지 않는다.
여러 스레드가 하나의 상태 플래그를 참조하고 수정해야 할 때 사용되며, 주로 읽기와 쓰기 간 충돌이 없고 복합 연산이 필요하지 않은 상태 플래그에서 활용된다. 예를 들어, 스레드를 종료하거나 중지하는 신호를 전달할 때 많이 사용된다.
참고 자료
[Java] 동기화 - synchronized와 volatile, Atomic Class에 대하여.