자바
Java Volatile & Atomic & Synchronized
모디(modi)
2020. 5. 4. 18:15
public void atomicInteger1() {
AtomicInteger atomic = new AtomicInteger();
System.out.println("value : " + atomic.get()); // 0
AtomicInteger atomic2 = new AtomicInteger(10);
System.out.println("value : " + atomic2.get()); // 10
}
Java에는 Concurrent 문제를 해결하는 데 3가지 방법이 있다.
- volatile 이용
- Atomic 클래스 이용
- synchronized 이용
- volatile
- 왜 필요한가?
- 각각의 컴퓨터에서 어플리케이션을 실행하면, 각 쓰레드는 main memory에서 읽어온 변수 값을 각 CPU의 Cache로 복사하여 읽는다.
- 각 쓰레드가 같은 java 변수값을 가져왔다고 쳐도, 쓰레드가 CPU Cache에 저장된 값을 변경하고 메모리에 제때 쓰지 않는다면 각 쓰레드에서 사용하는 변수값이 일치하지 않을 수가 있다.
- 한 쓰레드는 해당 변수를 카운트하고, 다른 쓰레드는 해당 변수를 ++ 한다고 가정하면, 카운트하는 쓰레드는 CPU캐시에만 업데이트 된 값을 가져올 수 없다는 것.
- 변수의 가시성 문제를해결할수있다.
- 가시성 문제
- CPU 메모리와 Main 메모리 중에서 어디서 가져온 값인지 알 수 없다.
- 여러 스레드에서 변수에 대한 변경 사항의 가시성을 보장
- 가시성 문제
- volatile변수는 컴퓨터의 메인 메모리부터 read하고, 메인 메모리에 직접 write 한다.
- 어떻게 쓰는가?
- 왜 필요한가?
private volatile int count = 0;
- atomic
- CAS(Compare and Swap) 방식
- 변수의 값을 변경하기 전에 기존의 값이 내가 예상하던 값과 같을 때만 새로운 값으로 할당
- CAS(Compare and Swap) 방식
public void atomicInteger2() {
AtomicInteger atomic = new AtomicInteger();
System.out.println("value : " + atomic.get()); // 0
atomic.set(100);
System.out.println("value : " + atomic.get()); // 100
}
- atomic vs volatile
- volatile 키워드는 오직 한개의 쓰레드에서 쓰기 작업을 하고, 다른 쓰레드는 읽기작업만을 할 때 사용
- AtomicBoolean, AtomicInteger는 여러 쓰레드에서 읽기/쓰기 작업을 병행할 수 있다.
- synchronized
- lock 방식
- 정리 예정 https://parkcheolu.tistory.com/15
출처
https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html
http://tutorials.jenkov.com/java-concurrency/volatile.html
https://readystory.tistory.com/53
https://codechacha.com/ko/java-atomic-integer/