많은 친구들이 키워드 휘발성에 대해 들었을 수도 있고 그것을 사용했을 수도 있습니다. Java 5 이전에는 논란의 여지가있는 키워드였습니다. 프로그램에서 사용하면 예상치 못한 결과가 발생했기 때문입니다. Java 5가 휘발성 키워드가 활력을 되 찾은 후에야만. 휘발성 키워드는 문자 그대로 이해하기 쉽지만 잘 사용하기 쉽지 않습니다.
1. 서문
JMM은 가시성을 보장하기 위해 휘발성 변수 정의, 최종 동기화 블록을 제공합니다.
휘발성으로 수정 된 변수의 경우 스레드는 변수를 사용할 때마다 변수의 가장 수정 된 값을 읽습니다. 휘발성은 쉽게 오용되어 원자 연산에 사용됩니다. 몇 가지 테스트 예제를 작성했습니다. 시도해 볼 수 있습니다.
2. 메인 프로그램
public class main {public static void main (string [] args)은 인터럽트 exception {list <sille> threadlist = new arraylist <sille> (); for (int i = 0; i <10; ++ i) {strook 스레드 = 새 스레드 (new Runnable () {@overridepublic void run () {single.holder.instance.add ();}}); ThreadList.Add (strule); thread.Strart ();} for (스레드 스레드 : thread : readlist) strule.join (); system.out.println (single.holder.instance.x);}}3. 싱글 톤 모드 테스트
1. 휘발성이없고 동기화되지 않습니다
클래스 싱글 {public int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (InterpruptedException e) {e.printstacktrace ();} ++ this.x;} public static class holder {public static instance = new Single ();}}}}}}}}출력 결과 : 8, 9 및 10이 모두 나타났습니다. 더 많이 실행하고 더 시도 할 수 있으며 다른 결과를 찾을 수 있습니다.
2. 휘발성이 있지만 동기화되지는 않습니다
클래스 싱글 {public volatile int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (InterpruptedException e) {e.printstacktrace ();} ++ this.x;} public static class {public static single instance = new Single ();}}.출력 결과 : 최대 발생 수는 9와 10입니다.
3. 휘발성이없고 동기화됩니다
클래스 싱글 {public int x = 0; public synchronized void add () {try {timeUnit.milliseconds.sleep (50);} catch (InterpruptedException e) {e.printstacktrace ();} ++ this.x;} public static holder {public static 싱글 인스턴스 = new Single ();}}.출력 결과 : 몇 번이나 실행하더라도 10이됩니다.
4. DCL에서 휘발성 적용에 대해 (이중 점검 잠금)
공개 클래스 Lazysingleton {private int nodefield; private static lazysingleton 인스턴스; 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 인스턴스; // (6)} public int getSomefield () {return this.somefield; // (7)}}우선, 왜이 글쓰기 방법이 Java에서 작동하지 않는지 설명하겠습니다!
Thread I가 처음으로 GetInstance () 메소드를 호출한다고 가정하고 Thread II도 GetInstance () 메소드 및 GetSomefield () 메소드를 호출한다고 가정합니다. 우리가 설명하고 싶은 것은 스레드 I (1)의 진술이 스레드 II (7)의 진술에 앞서 일어나지 않는다는 것입니다. Thread II가 getInstance () 메소드의 명령문 (2)을 실행할 때, 인스턴스에 대한 액세스가 동기 블록에 있지 않기 때문에, 스레드 II는 문장 (5)에서 인스턴스에 쓰기 I의 쓰기를 관찰 할 수 있거나 보지 않을 수 있습니다. 먼저 인스턴스의 값이 비어 있지 않다고 가정하므로 스레드가 인스턴스를 작성하는 것을 관찰합니다. 이 시점에서 Thread II는 명령문 (6)을 실행 하고이 인스턴스의 값을 직접 반환 한 다음이 인스턴스에서 getSomefield () 메소드를 호출합니다. 이 방법은 동기화없이 호출됩니다. 따라서 스레드 II의 전체 작동은 동기화없이 호출됩니다. 이것은 스레드 I의 진술 (1)과 스레드 II의 진술 (7) 사이에 관계가 없다는 것을 보여준다. 이는 Thread II가 문장 (1)에 약간의 값에 의해 Sured I에 의해 작성된 값을 관찰하지 못할 수 있음을 의미합니다. 이것이 DCL의 문제입니다. 말도 안돼? DCL은 원래 동기화를 피하기 위해 의도 되었으며이 목표를 달성했습니다. 정확하게는 이것이 결국 처벌을 받았기 때문입니다. 그러한 버그가 발견 될 확률은 복권에서 이길 확률보다 훨씬 낮고 도망 치고 있지만 그러한 프로그램에는 심각한 버그가 있습니다. 더 끔찍한 것은 그것이 일어나더라도 DCL에 의해 야기되었다고 생각하지 않을 것입니다.
내 이해는 Thread I과 Thread II 모두 자체 작업 저장소를 가지고 있다는 것입니다. 스레드 I 후 인스턴스를 생성 한 후 메모리로 새로 고침 할 시간은 불확실하므로 스레드 II가 문 (1)에 약간의 값에 의해 작성된 값을 관찰 할 수 없을 가능성이 있습니다.
따라서 Java 5에 추가 된 규칙이 추가되기 때문에 :
• 휘발성 필드에 동일한 필드에 대한 휘발성 필드에 작업을 작성하십시오.
이 규칙을 사용하여 인스턴스를 휘발성으로 선언 할 수 있습니다. 즉, 개인 휘발성 정적 Lazysingleton 인스턴스;
이 규칙에 따르면, 우리는 스레드 I (5) -> 스레드 II (2) (즉, 스레드)의 문장을 얻을 수 있습니다. 단일 스레드 규칙에 따라 스레드 I (1) -> 스레드 I (5)의 문장과 스레드 II (7)의 문장 (7)의 문장 (7)에 따르면, 나사산 II (7)의 문장이 있습니다. 문 (1)에서 스레드 I의 값에 대한 값과 프로그램은 올바른 동작을 얻을 수 있습니다.
보충 : Java5 이전에는 최종 필드의 동기 의미와 다른 변수 사이에는 차이가 없습니다. Java5에서, 최종 변수가 생성자에 설정되면 (이 참조가 생성자에 누출되지 않도록하는 경우), 다른 스레드는 생성자에 값이 설정된 값을 확실히 볼 수 있습니다. DCL의 문제점은 객체의 멤버 변수의 기본값을 볼 수 있으므로 Lazysingleton의 일부 필드 변수를 최종으로 설정하여 Java5에서 올바르게 실행할 수 있다는 것입니다.
위의 내용은 편집자가 소개 한 Java의 휘발성 키워드에 대한 지식입니다. 나는 그것이 모두에게 도움이되기를 바랍니다!