Tôi đọc lớp FutureTask trong jsr166, thấy rằng đối tượng kết quả là không bay hơi, các chú thích trong mã là "không bay hơi, được bảo vệ bởi nhà nước đọc/ghi" dòng 75, trạng thái là biến động int. Tôi đã đọc Mô hình bộ nhớ Java từ Java Language Spec, nhưng không tìm thấy câu trả lời chính xác. Có ai biết lý do không?tại sao đối tượng kết quả trong FutureTask là không dễ bay hơi?
8
A
Trả lời
5
xem xét chương trình này:
volatile int state;
Integer result;
void succeed(Integer result)
if(state==PENDING) vr0
this.result = result; w1
state = DONE; vw1
Integer peekResult()
if(state==DONE) vr2
return result; r2
return null;
Nếu không ổn định đọc vr2
thấy DONE
, nó có nghĩa là nó sẽ xảy ra sau khi biến động ghi vw1
. Vì vậy, chúng tôi đã xảy ra trước khi các mối quan hệ: w1 -> vw1 -> vr2 -> r2
. Do đó, viết w1
hiển thị để đọc r2
.
Tuy nhiên succeed()
không phải là chủ đề an toàn, vì vr0
và vw1
không phải là nguyên tử. Nếu chúng tôi sử dụng CAS
void succeed(Integer result)
if(compareAndSet(state, PENDING, DONE)) vr0+vw0
this.result = result; w1
nó sẽ khắc phục vấn đề nguyên tử. Tuy nhiên, hiện tại, w1
không nhất thiết hiển thị đối với r2
. Các hiệu ứng nhớ rào cản của CAS là loại giống như
void succeed(Integer result)
if(state==PENDING) vr0
state=DONE; vw0
this.result = result; w1
Chúng tôi có ở đây vw0 -> vr2 -> r2
, nhưng w1
không nằm trong chuỗi, không có w1 -> r2
Chúng ta phải làm những ghi biến động state=DONE
sau w1
thành lập xảy ra trước chuỗi.
void succeed(Integer result)
if(state==PENDING) vr0
state=TMP; vw0
this.result = result; w1
state=DONE; vw1
hoặc trong CAS
void succeed(Integer result)
if(compareAndSet(state, PENDING, TMP)) vr0+vw0
this.result = result; w1
state=DONE; vw1
câu trả lời rất hữu ích, hiểu thêm rõ ràng – taigetco