Tôi đã xem xét OpenJDK source code của CopyOnWriteArrayList
và có vẻ như tất cả các hoạt động ghi được bảo vệ bởi cùng một khóa và hoạt động đọc không được bảo vệ. Theo tôi hiểu, dưới JMM tất cả các truy cập vào một biến (cả đọc và viết) nên được bảo vệ bằng khóa hoặc hiệu ứng sắp xếp lại có thể xảy ra.Làm thế nào để CopyOnWriteArrayList có thể an toàn luồng?
Ví dụ, set(int, E)
phương pháp chứa những dòng này (trong tủ có khoá):
/* 1 */ int len = elements.length;
/* 2 */ Object[] newElements = Arrays.copyOf(elements, len);
/* 3 */ newElements[index] = element;
/* 4 */ setArray(newElements);
Phương pháp get(int)
, mặt khác, chỉ làm return get(getArray(), index);
.
Theo hiểu biết của tôi về JMM, điều này có nghĩa là get
có thể quan sát mảng trong trạng thái không nhất quán nếu câu 1-4 được sắp xếp lại như 1-2 (mới) -4-2 (copyOf) -3.
Tôi có hiểu JMM không chính xác hoặc có bất kỳ giải thích nào khác về lý do tại sao CopyOnWriteArrayList
có an toàn không?
Cảm ơn bạn. Tôi đã bỏ lỡ một thực tế là mảng là 'dễ bay hơi'. – Fixpoint
Một chi tiết quan trọng là dễ bay hơi chỉ áp dụng cho tham chiếu mảng, chứ không áp dụng cho nội dung của mảng. Tuy nhiên, vì tất cả các thay đổi đối với mảng được thực hiện ** trước khi ** tham chiếu của nó được xuất bản, các bảo đảm dễ bay hơi mở rộng đến nội dung của mảng. – assylias