Java volatile introduction
The Java volatile keyword can be applied to Java variable declarations to force the Java VM to always read the variable value directly from main memory, and always write changes to the variable directly back to main memory immediately.
Non-volatile variable visibility problems
public class Exchanger { private Object object = null; private volatile boolean hasNewObject = false; public Object getObject() { while(!this.hasNewObject){ //busy wait } Object returnValue = this.object; this.hasNewObject = false; return returnValue; } public void setObject(Object object) { this.object = object; this.hasNewObject = true; } }

volatile로 선언하지 않는다면 Thread 1 은 setObject를 호출하여 채운 object 와 hasNewObject 변수의 값을 자신의 cpu register에만 채우고 있을 수 있다.
또한 Thread 2 는 getObject를 호출할때 이전에 set 된 Main memory의 old value 들을 read할 수 있으며 심지어 자신의 L1, L2 캐시의 값을 읽을 수도 있다.
이런 문제를 visibility 문제라고 한다.
Java volatile visibility guarantee

volatile로 선언하게 되면 Thread 1이 setObject를 호출할때 Thread 1 에 의해 visible한 모든 변수를 Main Memory에 업데이트 한다.
마찬가지로 Thread 2 는 getObject를 호출할때 volatile로 선언한 변수 와 Thread 2에 의해 visible한 모든 변수는 캐시가 아닌 main memory에서 직접 읽어온다.
Instruction reordering could break the Java volatile visibility guarantee
Instruction reordering은 volataile visibilty guarantee를 뿌실 수 있다.
Java volatile happens before guarantee
이를 막기 위한 Instruction reordering의 규칙
- volatile 변수로의 write는 무적권 마지막에 실행 될 수 있도록 해야함
- volatile 변수의 read는 무적권 제일 먼저 실행 될 수 있도록 해야함
Java volatile performance overhead
- 메인 메모리에 직접 read/ write 하는 만큼 오버헤드가 있다.
- volatile 키워드는 꼭 필요할 때만 쓰자
Java volatile is not always enough
public class Counter { private volatile int count = 0; public boolean inc(){ if(count == 10){ return false; } this.count++; return true; } }
- count 가 9인 상태에서 두 쓰레드가 동시에 inc를 호출 하는 경우
- 아다리가 잘 안맞으면 count 는 11이되고 모두 true를 반환 할 수 있다.
- 또한 java의 ++ 연산은 atomic하지 않다
- read of variable
- increment of variable
- write of variable
- → 여기도 아다리가 안 맞으면 결과가 10이 될 수 있다.
- 이건 count의 값과 관계 없음
- atomicinteger 를 사용하여 해결 가능