Đọc thông số kỹ thuật ngôn ngữ Java, tôi thấy đoạn trích này về lĩnh vực thức:Nếu bạn gán một đối tượng cho trường cuối cùng, các luồng khác sẽ thấy các bản cập nhật trước đó của các trường không phải là cuối cùng/không dễ bay hơi của đối tượng đó không?
Mô hình sử dụng cho các lĩnh vực cuối cùng là một đơn giản: Đặt các trường thức cho một đối tượng trong constructor của đối tượng đó; và không viết một tham chiếu cho đối tượng đang được xây dựng ở một nơi mà một chuỗi khác có thể nhìn thấy nó trước khi hàm tạo của đối tượng kết thúc. Nếu điều này được theo sau, sau đó khi đối tượng được xem bởi một chuỗi khác, thì chuỗi sẽ luôn thấy phiên bản được xây dựng chính xác của các trường cuối cùng của đối tượng đó . Nó cũng sẽ thấy các phiên bản của bất kỳ đối tượng nào hoặc các mảng được tham chiếu bởi các trường cuối cùng đó ít nhất là cập nhật làm trường cuối cùng là.
Link: https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5
Câu hỏi của tôi là, làm "phiên bản" Cập nhật trung bình? Điều này có nghĩa là các trường không cuối cùng/không bay hơi của một đối tượng được tham chiếu bởi một trường cuối cùng cũng sẽ được đọc từ bộ nhớ chính (không phải bộ đệm cục bộ) sau khi xây dựng?
Ví dụ
Vì vậy, chúng ta hãy nói thread #1
tạo ra một objectB
và đặt một trong phi chính thức/lĩnh vực non-volatile của nó.
Sau đó thread #2
bộ cùng lĩnh vực để một cái gì đó khác nhau, tạo ra một số khác objectA
với một lĩnh vực thức thiết lập như objectB
, sau đó đặt mà objectA
nơi nào đó mà thread #1
có thể lấy nó.
thread #1
sau đó nhận số objectA
và xem trường cuối cùng là objectB
. Có thể cho thread #1
để không thấy các thay đổi đối với objectB
được thực hiện bởi thread #2
?
Hoặc đây là một số mã hiển thị những gì tôi muốn nói:
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;
}
}
}
Mã này dường như để đọc các giá trị cập nhật, nhưng tôi không chắc chắn nếu đó là chỉ cần ra khỏi ngẫu nhiên may mắn.
Khá tốt cho câu hỏi đầu tiên. – lexicore