문제

오늘,직장에서 건너 왔어 volatile 키워드에서 Java.되지 않을 매우 잘 알고,그것으로 이 설명:

Java 이론과 실제:관리 변동성

주어진 세부사항에는 해당 문서에서 설명하는 키워드는 질문에,당신은 그것을 사용하거나 당신은 이제까지 볼 수있는 케이스를 사용할 수 있습니다에서 키워드는 올바른 방식으로?

도움이 되었습니까?

해결책

volatile 는 의미를 메모리에 대한 가시성.기본적으로,의 가치 volatile 필드 표시되는 모든 독자들(다른 스레드에서 특정)후 작성 작업이 완료되었습니다.없 volatile, 독자들은 일부를 볼 수 있는 비트 값입니다.

당신의 질문에 대답:예,사용 volatile 변수 여부를 제어하는 코드는 계속됩니다.루프 테스트 volatile 값을 계속되는 경우 true.조건을 설정할 수 있습을 false 를 호출하여"stop"방법입니다.루프 보고 false 종료될 때 그것은 값을 테스트합 후 중지 방법의 실행을 완료.

책"Java 동시에서 실습는"나는 매우 추천하는,좋은 설명 volatile.이 책에 기록합니다 같은 사람이 쓴 IBM 문서에서 참조하는 질문(사실,그는 그의 책에서 아래쪽의 문서에서).내용 volatile 가 무엇을 자신의 문서화"패턴 1 상태 플래그입니다."

당신이 원하는 경우는 방법에 대해 자세히 알아보려면 volatile 작동,에 읽어 자바 메모리 모델.는 경우에 당신은 넘어 가고 싶은 그 수준을 확인,좋은 컴퓨터 아키텍처 책아 Hennessy&Patterson 에 대해 읽을 캐시 일관성과 캐시 일관성입니다.

다른 팁

"...휘발성 수정을 보장하는 어떤 스레드를 읽는 필드 볼 것이 가장 최근에 쓴 값입니다." -조쉬 블로흐

당신이 생각하는 경우 사용 volatile, 에 읽어 패키지 java.util.concurrent 루는 원자니다.

이 위키에 게시 단일 패턴 쇼 휘발성 사용합니다.

중요한 포인트에 대 volatile:

  1. 동기화에서 Java 를 사용하여 가능 Java 키워드 synchronizedvolatile 고 잠깁니다.
  2. 자바에서,우리가 할 수 없 synchronized 변수가 있습니다.용 synchronized 키워드가 변수가 불법적 결과적으로 컴파일에 오류가 있습니다.를 사용하는 대신 synchronized 변수에서 Java 를 사용할 수 있습니다 java volatile 변수는 지시 JVM 스레드 값을 읽어 volatile 변수에서 주기억과하지 않는 캐시다.
  3. 변수가 공유되지 않은 사 여러 스레드가 다음을 사용할 필요가 없 volatile 키워드입니다.

를 들어의 사용법 volatile:

public class Singleton {
    private static volatile Singleton _instance; // volatile variable
    public static Singleton getInstance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null)
                    _instance = new Singleton();
            }
        }
        return _instance;
    }
}

우리가 만드는 인스턴스를 재시에 첫 번째 요청을 제공됩니다.

우리가 만들지 않는다 _instance 변수 volatile 다음 쓰레드가 인스턴스를 만들의 Singleton 통신할 수 없을 다른 스레드가 있습니다.그렇다면 쓰레드는 단일 인스턴스를 만들고 그 후 작성,CPU 손상 등,모든 다른 스레드 수 없다는 것의 가치를 보 _instance 으로 null 이 아닌 그리고 그들은 믿을 것입니다 그것은 여전히 할당 null 입니다.

그 이유는 무엇입니까?기 때문에 독자 스레드를 하지 않는 모든 잠금까지 작가의 스레드에서 나오는 동기화된 블록의 메모리가 동기화되지 않고의 가치 _instance 지 않을 것입 업데이트합니다.으로 휘발성한 키워드에서 Java,이에 의해 처리됩 자바 자체가 이러한 업데이트가 표시됩니다 모두에 의해 리더 스레드입니다.

결론: volatile 키워드 또한 통신하는 데 사용되는 콘텐츠의 메모리 사이 스레드입니다.

를 들어 사용없이 volatile:

public class Singleton{    
    private static Singleton _instance;   //without volatile variable
    public static Singleton getInstance(){   
          if(_instance == null){  
              synchronized(Singleton.class){  
               if(_instance == null) _instance = new Singleton(); 
      } 
     }   
    return _instance;  
    }

위의 코드입니다하지 않는 스레드에 안전합니다.하지만 그것은 확인 가치의 인스턴스를 다시 한 번 내에서 동기화된 블록(성능을 위해),JIT 컴파일러를 다시 정렬 할 수 있습니다 바이트 코드에서는 방식으로 인스턴스에 대한 참조로 설정하기 전에 생성자를 완료됩니다.이 방법은 코드를 지정해주()객체를 반환할 수 있는지 초기화되었습니다.하는 코드를 스레드에 안전하는 키워드 휘발성할 수 있습부터 사용 Java5 인스턴스에 대해 변수입니다.변수으로 표시되는 휘발성을 얻을만 볼 수 있을 다른 스레드가 한번 생성자의 개체가 완성된 그것의 실행은 완전히.

enter image description here

volatile 사용 Java:

Fail-반복기는 빠르 일반적으로 를 사용하여 구현 volatile 카운터는 목록에 있는 객체입니다.

  • 목록을 업데이트,카운터가 증가합니다.
  • 는 경우 Iterator 만들고 현재 값을의 카운터에 포함 Iterator 체입니다.
  • 는 경우 Iterator 작업 수행 방법 비교한 두 개의 카운터 값을 던졌 ConcurrentModificationException 면 그들은 다릅니다.

의 구현 fail-safe 반복기는 일반적으로 가벼운 무게.그들은 일반적으로 의존하의 속성에 특정한 목록을 구현의 데이터 구조입니다.일반적인 패턴이다.

휘발성하는 것이 매우 유용하지는 스레드.

하지 않는 것이어야 합 쓰기에 자신의 스레드,Java1.6 에는 많은 좋은 스레드 수영장이 있습니다.하지만 경우에 당신은 당신의 스레드를 알아야 합니다 어떻게 그것을 중지합니다.

패턴에 사용하는 쓰레드:

public class Foo extends Thread {
  private volatile boolean close = false;
  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}

알 수 있는 방법을 필요가 없을 위한 동기화

하나는 일반적인 예를 들어 사용에 대한 volatile 을 사용하는 것입 volatile boolean 변수로는 플래그를 종료하는 스레드가 있습니다.는 경우에 당신은 시작했고,스레드할 수 있을 안전하게 인터럽트에서 다른 스레드에,당신은 있을 수 있는 스레드 정기적으로 확인 플래그입니다.를 중지 그것은,플래그 설정을 사실이다.에 의해 만들의 플래그 volatile, 하는지 확인할 수 있습는 스레드가 확인 그것은 그것을 보는 설정되는 다음 시간에 그것은 그것을 검사하지 않고도 사용 synchronized 니다.

변수 선언 volatile 키워드가 두 가지 주요 특성을 특별하다.

  1. 가 있는 경우 휘발성 변수,그것은 캐시할 수 없습으로 컴퓨터(마이크로프로세서)를 캐시 메모리에 의해 어떤 thread.액세스상에서 일어났다.

  2. 이 있는 경우 쓰기 작업 가 휘발성 변수,그리고 갑자기 읽기 작업 요청,그것은 자주 묻는 질문에 대한 답변을 볼 쓰기 동작 완성될 것입니다 읽기 전에 작업.

두 위의 질을 추론하는

  • 모든 쓰레드를 읽 휘발성 변수는 확실히 읽고 최신 값입니다.지 않기 때문에 캐시 값을 오염 시킬 수 있습니다.또한 읽는 요청에만 부여 완료 후 현재 쓰는 작업입니다.

그리고 다른 한편으로,

  • 는 경우에 우리는 더 이상 조사 #2 에서 언급한,우리는 볼 수 있습니다 volatile 키워드가 있는 완벽한 방법을 공유 변수를 유지하고있다 'n'개의 스레드를 읽고만 하나의 쓰레드 액세스할 수 있습니다.일단 우리는 추가 volatile 키워드,그것은 이루어집니다.아니 어떤 다른 오버헤드에 스레드에 안전합니다.

Conversly,

할 수 없volatile 키워드 전적으로 만족하기에,공유 변수는 하나 이상의 쓰레드 액세스.

Yes,휘발성이어야 사용할 때마다 변경 가능한 변수에 의해 액세스할 수 있는 여러 쓰레드.그것은 매우 일반적인 쓰임새기 때문에 일반적으로 수행해야 할 두 개 이상의 원자 작업(예:체크인 변수의 상태를 수정하기 전에 그것),어떤 경우에 사용하는 동기화된 블록을 대신 합니다.

아무도 언급된 치료의 읽고 쓰기 동작을 위해 오고 두 변수는 유형입니다.읽고 쓰는 원자 작업에 대한 참조 변수를 위해 가장 원시적 변수를 제외하고,장기 및 더블변수 유형을 사용해야 하는 휘발성하는 키워드이 될 원자 작업입니다. @링크

제 생각에는,두 개의 중요한 시나리오 다른 것보다 중지에서 스레드는 휘발성 키워드를 사용:

  1. 를 확인할 잠금 메커니즘.에서 자주 사용되는 단일 디자인 패턴입니다.이 단일 객체해야 휘발성 선언.
  2. 가 깨우.실을 수도 있습에서 깨어 기도 호출이 없는 경우 알리 전화를 진행하실 수 있습니다.이 행동이라고 supurious 습니다.이 수 있는 무효화를 사용하여 조건부 변수(boolean flag).을 넣어 기다리()호출에는만큼 루프 플래그가 사실이다.그렇다면 스레드에서 깨어나기 전화를 어떤 이유로 인해 다른 이에게 통지/notifyall 다음을 발견하는 플래그가 여전히 진실이고 따라서 호출을 다시 기다려야합니다.을 호출하기 전에 통지 이 플래그를 설정을 사실이다.이 경우 boolean flag 로 선언되는 휘발성.

를 사용해야 합'휘발성'키워드 또는'동기화'와 다른 동시성 제어 도구와 기술을 너의 처리에있을 개발하는 경우 다중 스레드 응용 프로그램.예 응용 프로그램을 이어갈 수 있습니다.

는 경우는 응용 프로그램을 개발하는 것을 배포하여 서버 응용 프로그램(Tomcat,JBoss 로,Glassfish,etc.)당신은 없을 처리하는 동시성 제어로 자신을 그것은 이미 해결된 응용 프로그램에 의해 서버입니다.제가 기억이 올바르게 Java EE 표준을 금지하 어떤 동시성 제어에 servlet 및 Ejb,일부분이기 때문의'인프라'레이어는 당신이 있어야 해방에서 취급습니다.당신은 단지 않는 동시성 제어에서 이러한 응용 프로그램을 구현하는 경우 단독 개체입니다.이것도 이미 해결된 경우 니트 구성 요소를 사용하여 frameworkd 같은 봄입니다.

그래서 대부분의 경우에 자바 개발 응용 프로그램은 웹 응용 프로그램을 사용하여 IoC 와 같은 프레임워크 봄 또는 EJB,당신은 없을 것을 사용할 필요가'휘발성'.

volatile 만한 모든 쓰레드도 스스로 증가.예를 들어:카운터는 동일한 얼굴의 변수에서 동일한 시간입니다.그것은 사용하지 않는 대신 동기화 또는 원자나 다른 물건,완전히 만드는 읽기 동기화됩니다.십시오지 않는 다른 java 키워드가 있습니다.으로 보여주는 예 아래 휘발성 변수 작업도 원자 그들은 실패하거나 성공에 한 번입니다.

package io.netty.example.telnet;

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static volatile  int a = 0;
    public static void main(String args[]) throws InterruptedException{

        List<Thread> list = new  ArrayList<Thread>();
        for(int i = 0 ; i<11 ;i++){
            list.add(new Pojo());
        }

        for (Thread thread : list) {
            thread.start();
        }

        Thread.sleep(20000);
        System.out.println(a);
    }
}
class Pojo extends Thread{
    int a = 10001;
    public void run() {
        while(a-->0){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Main.a++;
            System.out.println("a = "+Main.a);
        }
    }
}

심지어 당신을 넣어 휘발성이나 결과 항상 차이가 있습니다.그러나 사용하는 경우 AtomicInteger 아래와 같이 결과를 항상 동일합니다.이와 같은 동기화한다.

    package io.netty.example.telnet;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;

    public class Main {

        public static volatile  AtomicInteger a = new AtomicInteger(0);
        public static void main(String args[]) throws InterruptedException{

            List<Thread> list = new  ArrayList<Thread>();
            for(int i = 0 ; i<11 ;i++){
                list.add(new Pojo());
            }

            for (Thread thread : list) {
                thread.start();
            }

            Thread.sleep(20000);
            System.out.println(a.get());

        }
    }
    class Pojo extends Thread{
        int a = 10001;
        public void run() {
            while(a-->0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.a.incrementAndGet();
                System.out.println("a = "+Main.a);
            }
        }
    }

그렇다,나는 그것을 사용하 꽤 많이-그것은 매우 유용하게 사용할 수 있습 멀티스레드 코드입니다.이 문서에서 당신이 지적하는 것입니다.가 있지만 두 가지 중요한 일이 마음에 부담:

  1. 만 사용해야 합 휘발성는 경우 완전히 무엇인지 이해가 고 그것이 다른 방법을 동기화됩니다.많은 상황에서 휘발성이 나타나 표면을 단순한 성능 대체 동기화할 때,종종 더 나은 의 이해를 휘발성 만들 것입 는 동기화만 는 옵션을 작동합니다.
  2. 휘발성하지 않는 실제로에서 작동 많은 오래된 Jvm,지 동기화됩니다.난 기억하고 문서 참조하는 다양한 수준의 지원에 다른 Jvm 은 그러나 불행하게도 나는 그것을 찾을 수 없습니다 지금이다.확실히 그것으로 사용하는 경우 Java pre1.5 또는 없는 경우에는 제어 Jvm 은 프로그램에서 실행됩니다.

절대적으로,그렇습니다.(단지에서 자바이지만,또한 C#.) 거기에 시간이 필요하신 경우에는 설정 값을 보장하는 원자 작업에서 귀하의 특정 플랫폼,int 또는 부울,예를 들어,하지만 필요하지 않습의 오버헤드 잠금 스레드.휘발성 키워드할 수 있는지 확인을 읽을 때 당신은 값을 얻을 수 현재 값이 아닌 캐시되었던 값이 그냥 사용해 쓰기에 다른 스레드가 있습니다.

각 스레드에 액세스한 휘발성 필드를 읽을 것이다 그것의 현재 값을 계속하기 전에,대신(잠재적으로)을 이용하여 캐시 값입니다.

만 멤버변수할 수 있습 휘발성 또는 일시적이다.

두 개의 서로 다른 사용한 휘발성의 키워드를 사용합니다.

  1. 을 방지하는 JVM 에서 값 읽기에서 등록(다고 가정으로 캐시),그리고 힘이 그 값을 읽을 수 있는 메모리에서.
  2. 의 위험을 줄여 메모리에서 일 오류가 있습니다.

을 방지하는 JVM 에서 값을 읽는 등록을 세력 값을 읽을 수 있는 메모리에서.

A 깃발이 바쁘 을 방지하기 위해 사용되는 스레드가 계속에서 디자이너가 포함되어 있습니다 바쁜 플래그가에 의해 보호되지 않은 잠금:

while (busy) {
    /* do something else */
}

테스트 스레드가 계속 될 또 다른 스레드를 끄 깃발이 바쁘:

busy = 0;

그러나,이후 바쁜 액세스하에서 자주 테스트 thread,JVM 을 최적화할 수 있습 테스트를 배치하여 값의 바쁜에,등록 후 테스트의 내용을 등록하지 않고 값을 읽어의 바에서는 메모리기 전에 모든 테스트입니다.테스트 실을 볼 수 없을 것이다 바쁜 변경 다른 스레드의 값만 변경이 바쁜 메모리에서의 결과로 교착 상태가 발생합니다.선언 깃발이 바쁘 volatile 력 값을 읽기 전에 테스트입니다.

의 위험을 줄여 일관성 메모리 오류가 있습니다.

를 사용하여 휘발성 변수의 위험을 줄일 메모리 오류성, 기 때문에,어떤 쓰 휘발성 변수 설정 "일어나기 전에" 과의 관계 이후의 읽기 같은 변수가 있습니다.즉 변경 휘발성 변수는 항상 볼 수 있게 다른 스레드입니다.

의 기법,읽기,쓰기 없는 일관성 메모리 오류라 원자 작업.

원자 중 하나는 액션을 효과적으로 발생하는 모든다.원자 활동을 멈출 수 없는 중간에:그것은 하나 발생하고,그것은 일어나지 않는다.부작용 없음의 원자 행동을 볼 수 있을 때까지 작업이 완료됩니다.

아래는 행동을 지정할 수 있는 원자:

  • 읽고 쓰기가 원자를 위한 변수를 참조 그리고 대부분의 기본 변수(모든 유형을 제외하고 길고 두 번).
  • 읽고 쓰기가 원자를 위한 모든 변수를 선언 휘발성 (를 포함하여 긴 두 변수).

Cheers!

휘발성 변수는 경량 동기화합니다.가시성 의 최신 데이터가 모든 쓰레드가 요구와 자성이 손상될 수 있습,이러한 상황에서 휘발성 변수이어야 바람직하다.에 읽 휘발성 변수를 항상 가장 최근의 작성에 의해 수행 스레드 이후 그들은 어느 쪽도에 캐시 등록이나 캐시 다른 프로세서는 볼 수 없습니다.휘발성는 잠금 해제 됩니다.내가 사용하는 휘발성 때,시나리오를 충족하는 조건으로 위에서 언급된다.

휘발성는 다음과 같습니다.

1>읽기와 쓰기의 휘발성 변수에 의해 서로 다른 스레드에서 항상 기억,지에서 스레드의 자신의 캐쉬하거나 cpu register.그래서 각 스레드가 항상 거래의 최신 값입니다.2>경우 2 개의 다른 스레드와 함께 작동 동일한 인스턴스 또는 정적 변수에 힙,하나 볼 수 있습니다 기타의 작업이다.시미 manson 의 블로그에서이다.하지만 휘발성는 데 도움이 여기에.

다음과 같은 완전히 코드를 실행하는 방법을 보여 줍니다 숫자의 스레드를 실행할 수 있습에서 미리 정의된 주문 및 인쇄 출력하지 않고 동기화를 사용하여 키워드를 사용합니다.

thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3

이를 달성하기 위해 사용될 수 있습 다음과 같은 전체 본격적인 실행 코드입니다.

public class Solution {
    static volatile int counter = 0;
    static int print = 0;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread[] ths = new Thread[4];
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new Thread(new MyRunnable(i, ths.length));
            ths[i].start();
        }
    }
    static class MyRunnable implements Runnable {
        final int thID;
        final int total;
        public MyRunnable(int id, int total) {
            thID = id;
            this.total = total;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                if (thID == counter) {
                    System.out.println("thread " + thID + " prints " + print);
                    print++;
                    if (print == total)
                        print = 0;
                    counter++;
                    if (counter == total)
                        counter = 0;
                } else {
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        // log it
                    }
                }
            }
        }
    }
}

다음 github 링크 추가 정보는 적절한 설명이 있습니다.https://github.com/sankar4git/volatile_thread_ordering

에서 오라클 문서 페이지, 의 필요에 대한 휘발성 변수가 발생한 수정하는 일관성 메모리 문제점:

를 사용하여 휘발성 변수 위험을 줄이의 일관성 메모리 오류는,때문에 어떤 작성하 휘발성 변수를 설정하는 일이 관계 전과 후속 읽은 변수가 있습니다.

즉 변경 volatile 가변은 항상 볼 수 있게 다른 스레드입니다.그것은 또한 때에 스레드를 읽 휘발성 변수,그것을 본 아니라 최신 변경 volatile, 이지만,또한 부작용 코드는지도 변경합니다.

로에서 설명 Peter Parker 응답에서의 부재 volatile 수정자,각 스레드 스택할 수 있는 자신의 복사본 변수입니다.하여 변수 volatile, 메모리의 일관성의 문제가 해결되었습니다.

jenkov 튜토리얼 페이지에 대한 더 나은 이해합니다.

에서 봐야 관련 SE 질문에 대한 좀 더 자세한 사항에서의 휘발성용 케이스를 사용하 volatile:

차이를 변동성과 동기화에 Java

하나는 실제적인 사용 경우:

당신은 많은 스레드를 인쇄할 필요가 현재 시간에 특정 형식의 예를 들어: java.text.SimpleDateFormat("HH-mm-ss").Yon 있을 수 있는 하나의 클래스로 전환하는 현재 시간으로 SimpleDateFormat 업데이트 변수를 위해 모든 하나의 두 번째입니다.모든 다른 스레드가 사용할 수 있습 휘발성 변수를 인쇄 현재 시간을에서 로그 파일이 있습니다.

A 휘발성 변수 이 비동기적으로 수정에 의해 동시 실행 스레드에서 옵션을 선택해야 합니다.하는 것은 허용되지 않는다는 지역의 사본을 변수의에서 다른 값을 현재에서 개최되는"기본"메모리입니다.효과적 변수를 선언한 휘발성되어 있어야 합 데이터 동기화 모든 쓰레드,그래서 그 때마다 당신은에 액세스하거나 업데이트 변수에서 어떤 thread,모든 다른 스레드에 즉시 동일한 값입니다.의 과정,그것을 가능성이 휘발성 변수는 더 높은 액세스 및 업데이트 오버헤드 보다는"일반"변수,이후 이유는 스레드에 할 수 있는 자신의 복사본을 가지고있는 데이터에 대한 더 나은 효율성이 있습니다.

할 때 필드를 선언한 휘발성 컴파일러 및 런타임에 이 변수를 공유하고는 작업을 하지 않아야 순서를 바꾸는 다른 메모리 작업입니다.휘발성 변수가 캐쉬하지 않는 레지스터에 또는에서 캐시들이 어디에 숨겨진에서 다른 프로세서를,그래서 읽기의 휘발성 변수를 반환한 가장 최근에 작성하여 어떤 thread.

에 대한 참조하십시 http://techno-terminal.blogspot.in/2015/11/what-are-volatile-variables.html

휘발성는 경우 키를 사용 변수는 스레드를 읽고 이 변수는 동일한 값입니다.지금 당신이 가지고 있는 경우 여러 쓰레드를 읽고 쓰는 변수들 변수는 휘발성이 충분하지 않고 데이터가 손상되었습니다.이미지 스레드를 읽고 동일한 값을 가지고 있지만 각각의 하나는 일 chages(말한 증가 카운터)을 때,쓰기에 다시 메모리,데이터 무결성되어 있습니다.는 데 필요한 이유입하 varible 동기화(다른 방법도 가능)

는 경우는 변경 내용에 의해 행해 1 개 스레드 및 다른 사람을 필요로 그냥 이것을 읽을 가치,휘발성이 될 것입니다 적합합니다.

Jenkov 설명:

Java 휘발성 키워드 표시하는 데 사용됩 Java 변수로는"주 메모리에 저장되".더 정확하게는 각을 읽의 휘발성 변수에서 읽을 수 있는 컴퓨터의 주 메모리,고지에서는 CPU 캐시고 모든 쓰 휘발성 변수가 기록됩니다 주요 메모리만을 위해서 CPU cache.

실제로,이후 자바 5volatile 키워드는 보증 보다 더 그 휘발성 변수가 쓰고 읽을에서 주요 메모리입니다.

그것은 확장성을 보장 그래서 라는 일어나기 전에는 보장한다.

성능 고려 사항의 휘발성

읽기와 쓰기의 휘발성 변수인 변수를 읽거나 기록합니다.에서 읽고 쓰기 메인 메모리보다 더 비싼 액세스는 CPU cache.액세스하 휘발성 변수하지 못하도록 명령 순서는 정상적인 성능을 향상시키는 기술입니다.따라서,만 사용해야 합 휘발성 변수를 정말 필요할 때 적용시성 의 변수입니다.

휘발성 변수가 기본적으로 사용되는 즉시 업데이트(높이)에서 주요 공유 캐시선 후 업데이트되도록 변경 내용을 반영하는 모든 worker threads immediately.

아래에 아주 간단한 코드를 요구 사항을 보여 줍 volatile 한 변수를 통제하기 위하여 사용되는 스레드에서 실행하는 다른 thread(이 중 하나는 시나리오 volatile 이 필요합니다.)

// Code to prove importance of 'volatile' when state of one thread is being mutated from another thread.
// Try running this class with and without 'volatile' for 'state' property of Task class.
public class VolatileTest {
    public static void main(String[] a) throws Exception {
        Task task = new Task();
        new Thread(task).start();

        Thread.sleep(500);
        long stoppedOn = System.nanoTime();

        task.stop(); // -----> do this to stop the thread

        System.out.println("Stopping on: " + stoppedOn);
    }
}

class Task implements Runnable {
    // Try running with and without 'volatile' here
    private volatile boolean state = true;
    private int i = 0;

    public void stop() {
        state = false;
    } 

    @Override
    public void run() {
        while(state) {
            i++;
        }
        System.out.println(i + "> Stopped on: " + System.nanoTime());
    }
}

volatile 사용하지 않: 당신이 볼 수 없을거야'에서 멈:xxx'메시지 후에도'를 중지에는:xxx'프로그램을 계속 실행됩니다.

Stopping on: 1895303906650500

volatile 을 사용: 당신이 볼'에서 멈:xxx'immediately.

Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300

Demo: https://repl.it/repls/SilverAgonizingObjectcode

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top