Các memory model section (17.4) của JLS mô tả chi tiết hợp lý ngữ nghĩa của volatile
và không volatile
đọc và ghi, cũng như tương tác với một số cấu trúc khác như màn hình nhập và thoát.Liệu so sánh và trao đổi nguyên tử có ghi đè lên một văn bản lười biếng mà không thấy nó?
Tuy nhiên, nó không giải thích hoàn toàn ngữ nghĩa của compareAndSwap
cũng không phải lazySet
trên lớp java.util.concurrent.Atomic *. Đối với compareAndSet
, bạn không có lời giới thiệu từ package javadoc:
compareAndSet and all other read-and-update operations such as getAndIncrement
have the memory effects of both reading and writing volatile variables.
lazySet
cung cấp lời giới thiệu đôi chút bí hiểm hơn:
lazySet has the memory effects of writing (assigning) a volatile variable
except that it permits reorderings with subsequent (but not previous)
memory actions that do not themselves impose reordering constraints with
ordinary non-volatile writes. Among other usage contexts, lazySet may apply
when nulling out, for the sake of garbage collection, a reference that is
never accessed again.
gì không phải là rõ ràng với tôi là cách họ tương tác. Nếu bạn phát hành một CAS (compareAndSet
) và một lazySet đến cùng một giá trị nguyên tử, trong đó CAS expectedValue khác với giá trị lazySet, có thể là CAS ghi đè lên giá trị lazySet không?
một cách rõ ràng hơn, đưa ra hai đề, T1 và T2, hoạt động trên chung một AtomicInteger atomic = new AtomicInteger();
như sau:
static CountDownLatch latch = new CountDownLatch(2);
T1
atomic.lazySet(5); // L1A
latch.countDown();
latch.await();
int val1 = atomic.get();
T2
atomic.compareAndSet(0, 10); // L2A
latch.countDown();
latch.await();
int val2 = atomic.get();
là val1 == val2 == 10
một kịch bản có thể ở đây? Thật vậy, có thể val1
hoặcval2
bao giờ là 10?
Các chốt không phải là cốt lõi cho câu hỏi - chúng chỉ là một cách để có cả hai chủ đề đợi cho đến khi thao tác kia được thực hiện và bắt đầu xảy ra trước giữa các hoạt động lazySet
và compareAndSet
thú vị trên mỗi chuỗi. đọc của nguyên tử để xem trạng thái (không có chúng, bạn chắc chắn có thể thấy ít nhất val2 == 10
, thoáng qua).
Đúng vậy, nhưng vấn đề là không thực sự về tái đặt hàng: thực sự là 'lazySet' và' compareAndSwap' không xuất hiện trên cùng một chuỗi, vì vậy không có thứ tự vốn có giữa chúng. Chúng sẽ xảy ra theo thứ tự _some_, và câu hỏi đặt ra là nhiều hay ít cho dù bản chất nguyên tử của CAS có nghĩa là sẽ không bao giờ ghi đè. – BeeOnRope
Đặt hàng ở đây đề cập đến các hoạt động bộ nhớ, không phải hướng dẫn; mà họ đang ở trên không phải là một yếu tố. CAS là một tải và một cửa hàng - kể từ lazySet áp dụng một rào cản cửa hàng _preceeding store_, nếu CAS đã xảy ra sau đó viết được đảm bảo để hoàn thành trước khi lazySet cập nhật nó. – tzaman
Có các bản ghi nhớ là các hướng dẫn liên quan duy nhất. Những chủ đề mà họ đang ở trên là quan trọng - trên cùng một chủ đề, sẽ không có vấn đề.Mặt khác, hai thao tác trên các luồng khác nhau không có thứ tự vốn có. Về cơ bản một tuyên bố như sau: "điều này có nghĩa là lazySet write sẽ không được phép sắp xếp lại nó" có ý nghĩa cho hai thao tác trên cùng một luồng, nhưng trên các luồng khác nhau chúng có thể xảy ra theo thứ tự, trừ các hạn chế được áp đặt bởi bất kỳ thực tế nào " đồng bộ hóa với "các hoạt động tại thời gian chạy (ví dụ, một đọc dễ bay hơi thấy một ghi dễ bay hơi từ một chủ đề khác). – BeeOnRope