인스 턴 스가 다중 스레드에서 사용되는 경우 개인 필드를 volatile
으로 선언해야합니까?getter 및 setter가있는 java :`volatile` 전용 필드
if(!stopRequested)
while(true)
i++;
:
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean stopRequested; // works, if volatile is here
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
의 설명은
while(!stopRequested)
i++;
이런 식으로 뭔가에 최적화되어 있다고 말한다 : Effective Java에서
는 코드가 휘발성없이 작동하지 않습니다 예를 들어이
stopRequested
의 추가 수정본이 보이지 않습니다. 배경 스레드에 의해, 그래서 그것은 영원히 반복됩니다. (BTW, 그 코드는 JRE7에 volatile
없이 종료됩니다.)
지금이 클래스 고려해야 다음과 같이
public class Bean {
private boolean field = true;
public boolean getField() {
return field;
}
public void setField(boolean value) {
field = value;
}
}
및 스레드를 :
public class Worker implements Runnable {
private Bean b;
public Worker(Bean b) {
this.b = b;
}
@Override
public void run() {
while(b.getField()) {
System.err.println("Waiting...");
try { Thread.sleep(1000); }
catch(InterruptedException ie) { return; }
}
}
}
위의 코드 휘발성 물질을 사용하지 않고 예상대로 작동 :
public class VolatileTest {
public static void main(String [] args) throws Exception {
Bean b = new Bean();
Thread t = new Thread(new Worker(b));
t.start();
Thread.sleep(3000);
b.setField(false); // stops the child thread
System.err.println("Waiting the child thread to quit");
t.join();
// if the code gets, here the child thread is stopped
// and it really gets, with JRE7, 6 with -server, -client
}
}
나는 공공 세터 때문에 c라고 생각한다. ompiler/JVM은 getField()
을 호출하는 코드를 절대로 최적화해서는 안되지만 this article에는 변경 가능한 스레드 안전 클래스를 만들기 위해 적용해야하는 "휘발성 빈"패턴 (패턴 # 4)이 있다고 표시됩니다. 업데이트 : 아마도이 기사는 IBM JVM에만 적용됩니까?
질문 : JLS의 어느 부분에서 공개 getters/setters가있는 private 프리미티브 필드가 volatile
으로 명시되어야한다고 명시 적으로 또는 암시 적으로 말합니까?
오랜 질문 죄송합니다. 문제를 자세히 설명하려고했습니다. 뭔가 명확하지 않은 경우 알려주십시오. 감사.
스레드를 취소하기 위해 해당 필드가 필요하지 않은 것처럼 스레드에서 인터럽트 된 플래그를 사용할 수 있습니다. –
@ NathanHughes, 이러한 클래스는 단지 최소한의 예제이며, 실제 코드는 다르며 스레드 인터럽트가 필요하지 않습니다. – khachik