Java의 Volatile 키워드에 대한 이해

4687 단어 javavolatile키워드
volatile라는 키워드는 아마도 많은 친구들이 들은 적이 있을 것이다. 아마도 모두 사용한 적이 있을 것이다.Java5 이전에는 프로그램에서 사용하면 의외의 결과를 초래할 수 있기 때문에 논란이 많았던 키워드였다.자바 5 이후에야volatile 키워드가 다시 살아났다.volatile 키워드는 글자상으로는 이해하기 쉽지만 사용하기가 쉽지 않다.
1. 앞말
JMM은volatile 변수 정의,final,synchronized 블록을 제공하여 가시성을 확보합니다.
volatile로 수식된 변수는 변수를 사용할 때마다 변수가 수정된 가장 큰 값을 읽습니다.volatile는 원자성 조작에 사용되기 쉽다.몇 가지 테스트의 예를 썼으니 여러분 한번 해 보세요.
2. 메인 프로그램

public class Main{
public static void main(String[] args) throws InterruptedException{
List<Thread> threadList = new ArrayList<Thread>();
for(int i=0; i<10; ++i){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Single.Holder.instance.add();
}
});
threadList.add(thread);
thread.start();
}
for(Thread thread : threadList)
thread.join();
System.out.println(Single.Holder.instance.x);
}
}
3. 단일 모드 테스트
1,volatile,synchronized가 없는 경우

class Single{
public int x = 0;
public void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
} 
출력 결과: 8, 9, 10이 모두 나타났습니다.많이 운행하고 많이 해 보면 다른 결과를 발견할 수 있다.
2,volatile,synchronized 없음

class Single{
public volatile int x = 0;
public void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
}
출력 결과: 최대 9와 10이 나타납니다.
3,volatile,synchronized 없음

class Single{
public int x = 0;
public synchronized void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
}
출력 결과: 몇 번 실행하든지 10.
4. volatile의 DCL(double check lock)에서의 응용

public class LazySingleton {
private int someField;
private static LazySingleton instance;
private LazySingleton() {
this.someField = new Random().nextInt(200)+1; // (1)
}
public static LazySingleton getInstance() {
if (instance == null) { // (2)
synchronized(LazySingleton.class) { // (3)
if (instance == null) { // (4)
instance = new LazySingleton(); // (5)
}
}
}
return instance; // (6)
}
public int getSomeField() {
return this.someField; // (7)
}
}
우선 왜 이런 작법은 자바에서 통하지 않는지 설명해 주세요!
만약에 스레드 I가 getInstance () 방법을 처음 호출한 것이고 그 다음에 스레드 II도 getInstance () 방법과 getSomeField () 방법을 호출했다. 우리가 설명하고자 하는 것은 스레드 I의 문장 (1) happen-before 스레드 II의 문장 (7) 이 아니다.스레드 II는 getInstance () 방법의 문장 (2) 을 실행할 때 instance에 대한 접근이 동기화 블록에 있지 않기 때문에 스레드 II는 스레드 I가 문장 (5) 에서 instance에 대한 쓰기를 관찰하지 못할 수도 있습니다. 즉, instance의 값이 비어 있을 수도 있고 비어 있을 수도 있습니다.우리는 먼저 instance의 값이 비어 있지 않다고 가정하고 스레드 I가 instance에 쓰는 것을 관찰했다. 이때 스레드 II는 문장(6)을 실행하여 이 instance의 값을 직접 되돌려주고 이 instance에 getSomeField () 방법을 호출한다. 이 방법도 어떠한 동기화 상황이 호출되지 않기 때문에 전체 스레드 II의 동작은 동기화되지 않은 상황에서 호출된다.이것은 스레드 I의 문장 (1) 과 스레드 II의 문장 (7) 사이에happen-before 관계가 존재하지 않는다는 것을 설명한다. 이것은 스레드 II가 실행 문장 (7) 에서 스레드 I가 문장 (1) 에서 someFiled에 쓴 값을 관측할 수 없다는 것을 의미한다. 이것이 바로 DCL의 문제이다.터무니없지, 그렇지?DCL은 원래 동기화를 피하기 위해 이 목적을 달성했다. 바로 그렇기 때문이다. 결국 벌을 받는다. 이런 프로그램에는 심각한 버그가 존재한다. 비록 이런 버그가 발견될 확률은 복권에 당첨될 확률보다 훨씬 낮고 순식간에 사라진다. 더욱 무서운 것은 DCL이 일으킬 것이라고 생각하지 않는다는 것이다.
내 이해는 스레드 I와 스레드 II는 모두 자신의 작업 저장소를 가지고 있으며, 스레드 I가 instance를 만든 후 메모리로 리셋하는 시간은 확실하지 않기 때문에 스레드 II가 실행 문장(7)에서 스레드 I가 문장(1)에 쓴 값을 관측하지 못할 가능성이 완전히 있다.
그러면 자바 5에 happen-before 규칙이 하나 더 추가되었기 때문입니다.
•volatile 필드에 대한 쓰기 작업happen-before 다음에 같은 필드에 대한 읽기 작업입니다.
이 규칙을 이용하여 우리는 instance를volatile, 즉:privatevolatile static LazySingleton instance로 성명할 수 있다.
이 규칙에 따라 우리는 스레드 I의 문장(5)->어 스레드 II의 문장(2), 단일 스레드 규칙에 따라 스레드 I의 문장(1)->어 스레드 I의 문장(5)과 어 스레드 I의 문장(2)->어 스레드 I의 문장(7), 전달 규칙에 따라 스레드 I의 문장(1)->어 스레드 I의 문장(7)을 얻을 수 있다. 이것은 스레드 I가 문장(1)에서 someFiled에 대한 쓰기 값을 관찰할 수 있음을 나타낸다.프로그램은 정확한 행위를 얻을 수 있다.
보충:java5 이전에final 필드의 동기화 의미는 다른 변수와 차이가 없습니다.java5에서final 변수는 구조 함수에서 설정이 완료되면(전제는 구조 함수에this 인용이 누설되지 않음), 다른 라인은 반드시 구조 함수에 설정된 값을 볼 수 있습니다.DCL의 문제는 바로 대상의 구성원 변수의 기본값을 보는 데 있다. 따라서 우리는 LazySingleton의 someField 변수를final로 설정하여java5에서 정확하게 실행할 수 있다.
위와 같은 내용은 여러분에게 소개된 Java의 Volatile 키워드에 대한 지식입니다. 여러분에게 도움이 되었으면 합니다!

좋은 웹페이지 즐겨찾기