, 나는 마지막 필드에 대한 발췌를 발견최종 필드에 개체를 할당하면 다른 스레드가 해당 개체의 비 최종/비 휘발성 필드의 이전 업데이트를 볼 수 있습니까? Java 언어 사양을 읽고
마지막 필드의 사용 모델은 간단 하나입니다 : 객체의 생성자에 개체에 대한 최종 필드를 를 설정; 객체의 생성자가 완료되기 전에 다른 스레드가 그것을 볼 수있는 장소에서 생성되는 객체에 대한 참조를 쓰지 마십시오. 이 을 따르는 경우 다른 스레드에서 개체를 볼 때 스레드는 항상 개체의 최종 필드의 올바르게 구성된 버전을 볼 수 있습니다. 최종 필드가 일 때 일 때 해당 필드가 참조하는 모든 객체 버전 또는 배열도 표시됩니다.
링크 : https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5
내 질문에, 않습니다 "버전"평균 업데이트입니까? 즉, 최종 필드에서 참조하는 객체의 비 최종/비 휘발성 필드는 구성 후에도 주 메모리 (로컬 캐시가 아님)에서 읽혀집니다.
예
는 그럼 thread #1
가 objectB
를 만들고 해당 비 최종/비 휘발성 필드 중 하나를 설정 가정 해 봅시다.
그런 다음 같은 분야는 뭔가 다른, 다음, objectB
로 설정 최종 필드와 다른 objectA
를 생성하는 thread #2
세트 thread #1
그것을 objectA
어딘가에 얻을 수있는 것을 넣습니다.
thread #1
은 objectA
이되고 최종 필드는 objectB
으로 표시됩니다. thread #1
에 objectB
의 변경 사항을 볼 수 없습니까? thread #2
으로 만드시겠습니까?
또는 여기가 무슨 뜻인지 보여주는 몇 가지 코드 :
이public class Test {
private static final ConcurrentLinkedQueue<A> myAs = new ConcurrentLinkedQueue<>();
private static long timer = System.nanoTime() + 3000000000L; // 3 seconds into the future
public static void main(String... args) {
B myB = new B("thread #1"); // Set in thread 1
new Thread(() -> {
myB.setString("thread #2"); // Set in thread 2
myAs.add(new A(myB));
}).start();
for(long i = 0; i < x; i = System.nanoTime()) {} // Busy-wait for about 3 seconds
System.out.println(myAs.poll().getB().getString()); // Print out value
}
public static class A {
private final B b;
public A(B b) {
this.b = b;
}
public B getB() {
return b;
}
}
public static class B {
private String s = null;
public B(String s) {
this.s = s;
}
public String getString() {
return s;
}
public void setString(String s) {
this.s = s;
}
}
}
코드는 업데이트 된 값을 읽을 것,하지만 그건 그냥 무작위로 운이 있는지 모르겠어요.
첫 번째 질문에 아주 좋습니다. – lexicore