@참고)
- 박철우 - 자바 volitile 키워드
문제상황
- DeadLock
- 두개 이상의 쓰레드가 자원을 소유한 상태로 서로가 소유한 락을 읽어오기 위해 경쟁하는 상태
- LiveLock
- 한 쓰레드가 이미 자원을 점유한 상태에서 다른 쓰레드가 그 자원을 사용하기 위해 무한정 대기상태에 빠지는 상태
- Starvation
- 다른 쓰레드가 락을 해제하지 않아 쓰레드가 임계영역에 진입하지 못하는 상태
- 쓰레드 간섭 → 동시성 문제 : Race Condition, Visibility Problem
- 하나의 자원에 여러 쓰레드가 사용하고자 할때 발생하는 문제
- 쓰레드 간섭은 서로 다른 쓰레드에서 두 연산이 동시에 실행되어 상태가 꼬이는 것
int i = 5; Thread 1 : i++; // reads value 5 Thread 2 : i++; // reads value 5 Thread 1 : // increments i to 6 Thread 2 : // increments i to 6 // i == 6 instead of 7

해결방법
- 운영 체제에서 동시성 문제를 예방하는 방법
- Bounded Waiting (DeadLock, Starvation 예방)
- Progress (LiveLock 예방)
- Mutual Exclusion (Race Condition, Visibiality Problem 예방)
- Mutex, Semaphore
- 자바에서 동시성 문제를 해결하는 방법
volatile
키워드volatile
키워드는 변수의 값을 저장할 때 cpu 캐시가 아닌 메인메모리에 직접 쓰기 작업을 수행 하고 변수의 값을 읽을 때도 메인메모리에서 직접 읽어 올것을 명시하는 키워드 입니다.- 따라서 Thread 1 에서는 쓰고 Thread 2 에서는 읽는 경우에
voliatile
키워드는 동시성을 보장합니다. - 하지만
volatile
키워드를 사용하여 Main Memory로 부터 변수를 읽기/쓰기하는 것은 CPU 캐시를 활용하는 것 보다 많은 비용이 요구됩니다.volatile
의 선언은 JVM 의 성능 향상 기술인 코드 재정리를 막기도 합니다. - 따라서
volatile
키워드는 변수의 visiablity 보장이 반드시 필요한 상황에 신중하게 사용해야합니다.
synchronized
키워드synchronized
키워드는 메서드, 변수 혹은 코드 블럭에 선언하여 다른 쓰레드의 해당 영역으로의 진입을 막는 역할을 할 수 있습니다.- 안전하지만 가장 비용이 큽니다.
java.util.concurrent
패키지의 atomic data type- e.g.)
AtomicInteger
,AtomicLong
, … - Atomic 클래스는 Compare-and-Swap 을 기용하여 동시성을 보장합니다.
- 여러 쓰레드에서 데이터를 write 해도 문제가 없습니다.
- Atomic 클래스는 synchronized 보다 적은 비용으로 동시성을 보장할 수 있습니다.
- 스트림 API 활용
@See Also)
- 쓰레드가 공유하는 자원에 대한 동시성을 해결하기 위한 위 방법들과는 별개로쓰레드가 자신의 고유한 자원을 보장받기 위해 사용하는 ThreadLocal 이라는 개념도 알아둡시다.