오늘 직장에서 저는 volatile
키워드를 Java로 보았습니다. 그것에 익숙하지 않아서이 설명을 찾았습니다.
해당 기사에서 해당 키워드에 대해 자세히 설명 했으므로 키워드를 사용하거나 올바른 방식으로이 키워드를 사용할 수있는 사례를 볼 수 있습니까?
답변
volatile
메모리 가시성에 대한 의미가 있습니다. 기본적으로 volatile
필드 값은 쓰기 작업이 완료된 후 모든 독자 (특히 다른 스레드)에게 표시됩니다. 이 없으면 volatile
독자는 업데이트되지 않은 값을 볼 수 있습니다.
귀하의 질문에 대답하기 위해 : 예, volatile
변수를 사용하여 일부 코드가 루프를 계속하는지 여부를 제어합니다. 루프는 volatile
값을 테스트하고 값이 계속되면 계속합니다 true
. false
“stop”메소드를 호출하여 조건을 설정할 수 있습니다 . 루프는 false
stop 메소드가 실행을 완료 한 후 값을 테스트 할 때보고 종료합니다.
제가 추천하는 ” 실제로 Java Concurrency “책에 대한 좋은 설명이 volatile
있습니다. 이 책은 질문에서 언급 된 IBM 기사를 쓴 동일한 사람이 작성했습니다 (사실, 해당 기사의 맨 아래에 그의 책을 인용합니다). 필자가 사용하는 volatile
기사는 “패턴 1 상태 플래그”라고합니다.
volatile
후드 아래에서 작동 하는 방법에 대한 자세한 내용을 보려면 Java 메모리 모델을 읽으십시오 . 이 수준을 넘어서려면 Hennessy & Patterson 과 같은 훌륭한 컴퓨터 아키텍처 책을 확인하고 캐시 일관성 및 캐시 일관성에 대해 읽으십시오.
답변
“… 휘발성 수정자는 필드를 읽는 스레드가 가장 최근에 작성된 값을 볼 수 있도록 보장합니다.” -Josh Bloch
사용 volatile
에 대해 생각하고 있다면 java.util.concurrent
원자 행동을 다루는 패키지 를 읽으십시오 . 싱글 톤 패턴
답변
에 대한 중요한 점 volatile
:
- 자바의 동기화는 자바 키워드를 사용하여 가능
synchronized
하고volatile
및 잠금. - Java에서는
synchronized
변수를 가질 수 없습니다 . 사용synchronized
변수와 키워드 불법 컴파일 오류가 발생합니다.synchronized
Java 에서 변수 를 사용하는 대신 javavolatile
변수를 사용하면 JVM 스레드가volatile
기본 메모리에서 변수 값을 읽고 로컬로 캐시하지 않도록 지시 할 수 있습니다. - 변수가 여러 스레드간에 공유되지 않으면
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
다른 스레드와 통신 할 수 없습니다. 따라서 스레드 A가 Singleton 인스턴스를 생성하고 생성 직후 CPU가 손상되면 다른 모든 스레드는 _instance
null이 아닌 값을 볼 수 없으며 여전히 null이 할당 된 것으로 간주합니다.
왜 이런 일이 발생합니까? 판독기 스레드는 잠금을 수행하지 않고 기록기 스레드가 동기화 된 블록에서 나올 때까지 메모리가 동기화 _instance
되지 않고 주 메모리에서 값 이 업데이트되지 않습니다. Java의 Volatile 키워드를 사용하면 Java 자체에서 처리되며 이러한 업데이트는 모든 독자 스레드에서 볼 수 있습니다.
결론 :
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 컴파일러는 생성자가 실행을 마치기 전에 인스턴스에 대한 참조가 설정되는 방식으로 바이트 코드를 재 배열 할 수 있습니다. 이는 getInstance () 메소드가 완전히 초기화되지 않았을 수있는 오브젝트를 리턴 함을 의미합니다. 코드를 스레드로부터 안전하게 만들기 위해 인스턴스 변수에 Java 5부터 키워드 volatile을 사용할 수 있습니다. 휘발성으로 표시된 변수는 객체 생성자가 실행을 마치면 다른 스레드에서만 볼 수 있습니다.
출처
volatile
Java 사용법 :
페일 패스트 반복기는 일반적으로volatile
목록 객체 의 카운터를 사용하여 구현됩니다 .
- 목록이 업데이트되면 카운터가 증가합니다.
- 를 만들면
Iterator
카운터의 현재 값이Iterator
개체에 포함됩니다 . - 때
Iterator
동작이 수행되고, 상기 방법은 두 개의 카운터 값을 비교하고,이 슬로우ConcurrentModificationException
가 다르면.
페일 세이프 반복기의 구현은 일반적으로 경량입니다. 이들은 일반적으로 특정 목록 구현 데이터 구조의 속성에 의존합니다. 일반적인 패턴은 없습니다.
답변
volatile
스레드를 중지하는 데 매우 유용합니다.
자신의 스레드를 작성하는 것이 아니라 Java 1.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
}
}
위의 코드 세그먼트 close
에서 while 루프 의 스레드 읽기 는를 호출 하는 스레드 와 다릅니다 close()
. 휘발성이 없으면 루프를 실행하는 스레드가 변경 사항을 닫을 수 없습니다.
동기화가 필요없는 방법에 주목
답변
volatile
사용하는 일반적인 예 는 volatile boolean
변수를 플래그로 사용하여 스레드를 종료하는 것입니다. 스레드를 시작했는데 다른 스레드에서 안전하게 중단하려면 스레드가 주기적으로 플래그를 확인하도록 할 수 있습니다. 중지하려면 플래그를 true로 설정하십시오. 플래그를 작성하면 volatile
검사중인 스레드가 다음 번에 synchronized
블록을 사용할 필요없이 검사 할 때 설정되었음을 확인할 수 있습니다 .
답변
volatile
키워드로 선언 된 변수 에는 두 가지 주요 특성이있어 특별합니다.
-
휘발성 변수가 있으면 스레드가 컴퓨터의 (마이크로 프로세서) 캐시 메모리에 캐시 할 수 없습니다. 액세스는 항상 주 메모리에서 발생했습니다.
-
휘발성 변수에 대한 쓰기 작업 이 있고 갑자기 읽기 작업 이 요청되면 읽기 작업 이전에 쓰기 작업이 완료됩니다 .
위의 두 가지 특성으로 인해
- 휘발성 변수를 읽는 모든 스레드는 확실히 최신 값을 읽습니다. 캐시 된 값은이를 오염시킬 수 없기 때문입니다. 또한 읽기 요청은 현재 쓰기 작업이 완료된 후에 만 부여됩니다.
반면에
- 위에서 언급 한 # 2 를 자세히 조사하면
volatile
키워드가 ‘n’개의 판독기 스레드와 하나의 기록기 스레드 만 있는 공유 변수를 유지하는 이상적인 방법 임을 알 수 있습니다 .volatile
키워드를 추가하면 완료됩니다. 스레드 안전에 대한 다른 오버 헤드가 없습니다.
반대로
우리 는volatile
키워드를 단독으로 사용할 수 없으며 , 액세스하는 작성자 스레드 가 둘 이상인 공유 변수를 만족시킬 수 없습니다 .
답변
long 및 double 변수 유형에 대한 읽기 및 쓰기 작업 처리에 대해서는 아무도 언급하지 않았습니다. 읽기 및 쓰기는 volatile 키워드를 원자 연산으로 사용해야하는 long 및 double 변수 유형을 제외하고 참조 변수 및 대부분의 원시 변수에 대한 원자 연산입니다. @링크