Điều này có nghĩa là việc đặt tham chiếu KHÔNG phải là một hoạt động nguyên tử trong và của chính nó?
Đặt biến tham chiếu là nguyên tử, nhưng thao tác nguyên tử không nhất thiết phải an toàn theo luồng. Hãy để tôi giải thích.
Nguyên tử có nghĩa là bất kỳ người quan sát nào (chủ đề) đều thấy giá trị cũ hoặc giá trị mới của biến và không phải cái gì khác. Nó không có nghĩa là tất cả các nhà quan sát thấy giá trị mới khi họ nhìn vào biến. (Và như @Tom chỉ ra, nguyên tử của biến tham chiếu không nói gì về tính chất nguyên tử của đối tượng mà nó tham chiếu.)
Đối với tất cả các nhà quan sát thấy giá trị mới trong biến, cần có sự đồng bộ hóa nào đó trên. Đối với một bản cập nhật cho một biến, điều này sẽ xảy ra nếu:
- biến được khai báo là
volatile
, hoặc
- truy cập/cập nhật vào biến được đồng bộ hóa bằng khóa màn hình nguyên thủy giống nhau.
Một biến được bao bọc trong "AtomicXxx" class có liên quan cũng sẽ được thread-an toàn, mặc dù bạn vẫn thường sử dụng một trong các lớp này nếu bạn muốn tránh ổ khóa và bạn muốn làm những thứ như nguyên tử "so sánh và thay thế".
Một lần nữa, điều này chỉ áp dụng cho tính an toàn của chủ đề của tham chiếu đối tượng. Nếu trạng thái của đối tượng không phải là cũng được đồng bộ hóa đúng cách, một luồng cũng có thể thấy giá trị cũ cho thuộc tính của đối tượng, v.v.
Nguồn
2010-03-05 04:20:09
Ví dụ của bạn không hoàn toàn an toàn cho chuỗi. Nếu danh sách được xuất bản không đúng, bạn có thể không đọc đúng nội dung (mặc dù việc thực hiện 'LinkedList' có thể cho phép bạn thoát khỏi điều này nếu nó trống). –
@Tom: bạn có nghĩa là các chủ đề khác có thể nhận được giá trị cũ, được lưu trong bộ nhớ cache cho trường someList hoặc trường someList có thể thực sự được "viết một nửa" không? – radai
@ hatchetman82 Tôi có nghĩa là sau khi tài liệu tham khảo mới được đọc, đối tượng nó trỏ đến có thể không được cập nhật hoàn toàn. Vì vậy, nếu tôi không công khai 'java.awt.Point (1, 2) 'mới, tôi có thể đọc đối tượng trong một luồng khác nhưng các trường' x' và 'y' vẫn có thể bằng không. –