Trường hợp sử dụng của tôi yêu cầu được phân bổ trực tiếp ByteBuffer
được ghi một lần và sau đó được đọc bởi nhiều chủ đề đồng thời. Tất cả các lần đọc là tuyệt đối và vì vậy tôi không bao giờ quan tâm đến trạng thái của bộ đệm (vị trí, giới hạn, dấu).Tại sao đọc tuyệt đối từ một ByteBuffer không được coi là an toàn thread?
This article trên bộ đệm byte bởi Keith Gregory cảnh báo rằng thậm chí tuyệt đối đọc không được coi là thread-safe:
ByteBuffer
chủ đề an toàn được bao phủ trongBuffer
javadoc; phiên bản ngắn gọn là các bộ đệm không phải là chủ đề an toàn. Rõ ràng, bạn không thể sử dụng định vị tương đối từ nhiều luồng không có điều kiện chủng tộc, nhưng thậm chí vị trí tuyệt đối không được đảm bảo (bất kể bạn nghĩ gì sau khi xem các lớp triển khai).
(tôi nhấn mạnh)
Do cảnh báo này, tôi trước mỗi việc đọc từ bộ đệm byte với một cuộc gọi đến duplicate
. Điều này là dễ dàng đủ, nhưng phân bổ đối tượng bổ sung trên mỗi đọc duy nhất có tôi tò mò tại sao nó thực sự cần thiết.
Mặc dù từ chối trách nhiệm wizardly Keith, tôi đã nhìn vào OpenJDK của implementation của một đọc tuyệt đối từ một bộ đệm byte trực tiếp:
public byte get(int i) {
return ((unsafe.getByte(ix(checkIndex(i)))));
}
Bạn có thể thấy rằng nó chỉ đơn giản là đại biểu Unsafe.getByte(long)
, mà "lấy một giá trị từ một định địa chỉ bộ nhớ ".
Tôi hiểu rằng các triển khai khác nhau có thể tồn tại, nhưng điều gì không thể an toàn cho luồng về hoạt động này một cách hợp lý? Hợp đồng Buffer
có đơn giản từ chối đảm bảo an toàn luồng cho các lần đọc tuyệt đối để tránh sự nhầm lẫn của một lớp an toàn một phần không? Hoặc nếu cảnh báo được biện minh cho việc ghi đồng thời, thì tình trạng của tôi, trong đó bộ đệm byte là chưa sửa đổi sau khi tạo? Ngoài ra, bất cứ điều gì sẽ thay đổi khi sử dụng một số MappedByteBuffer
thay thế?
liên quan:
- What is the use of ByteBuffer in Java?
- The Java ByteBuffer – a crash course
- Atomic read then write of part of a ByteBuffer in Java
- Options to make Java's ByteBuffer thread safe
Hmm. Rất nhiều ý kiến không được chứng minh ở đó.Ví dụ: "Tôi không nghĩ rằng điều này sẽ đưa mô hình bộ nhớ Java vào tài khoản". Việc thực hiện * phải * (a) tuân thủ đặc tả được nêu trong Javadoc và (b) đưa mô hình bộ nhớ Java vào tài khoản khi thực hiện điều đó. – EJP
@EJP Nhận xét về Mô hình Bộ nhớ Java dường như đề cập đến các bộ đệm trực tiếp, nằm bên ngoài vùng heap Java. Về cơ bản chúng là các phép toán IO được ánh xạ trên bộ nhớ, và các thao tác IO trên các tệp (hoặc bất kỳ thứ gì bên ngoài vùng/ngăn xếp Java/v.v.) không phải tuân theo mô hình Bộ nhớ Java –
Ngay cả khi bỏ qua các vấn đề hiển thị bạn sẽ nhận được mà không cần đồng bộ hóa thích hợp, phương thức 'get' không phải là nguyên tử. Nó truy cập mảng dữ liệu được chia sẻ và thực hiện kiểm tra chỉ mục bao gồm việc đọc trạng thái chia sẻ 'giới hạn'. – isnot2bad