2015-08-27 14 views
5

Tôi đọc trong một cuốn sách đọc trong ConcurrentHashmap không đảm bảo trạng thái được cập nhật gần đây nhất và đôi khi nó có thể mang lại giá trị gần hơn. Điều này có đúng không?Hoạt động đọc trong ConcurrentHashMap có đáng tin cậy về giá trị trả lại không?

Tôi đã đọc javadocs của nó và nhiều blog có vẻ như nói khác (tức là nó chính xác).

Điều nào là đúng?

+0

Bạn định đọc dữ liệu như thế nào? –

+0

sử dụng đơn giản get() –

+1

Sau đó, bạn không nên lo lắng, nó sẽ trả về giá trị chính xác nhất. –

Trả lời

0

Đó là bản chất của sự tương tranh. Bất kỳ bộ sưu tập đồng thời nào cũng có thể cung cấp cho bạn giá trị cũ trong một trường nếu thao tác ghi hiện đang chờ xử lý không được hoàn tất một cách an toàn. Đó là trong mọi trường hợp những gì bạn phải mong đợi. Các bộ sưu tập được thực hiện cho đồng thời sẽ không cung cấp cho bạn các giá trị bị hỏng hoặc bị hỏng nếu bạn truy cập chúng từ nhiều luồng, nhưng chúng có thể cung cấp cho bạn các giá trị cũ, nếu viết không được thực hiện.

+1

Nếu giá trị không được ghi đè, thì đó không phải là giá trị cũ, đó là giá trị hiện tại ... Chắc chắn nó không cung cấp cho bạn giá trị tương lai, mà là bình thường – Dici

+0

Có. Nhưng với đồng thời, có thể đọc một giá trị * trong khi * nó được viết. Bộ sưu tập "bình thường" làm điều gì đó không xác định nếu điều đó xảy ra. Các bộ sưu tập đồng thời cung cấp cho bạn giá trị cũ hoặc khối cho đến khi viết xong. – Nitram

+0

Bạn không thể nhìn vào 'Collections.SynchronizedCollection' cho điều đó. Đây là trình bao bọc chặn hiệu suất thấp đơn giản xung quanh bộ sưu tập bình thường. Hãy xem triển khai ConcurrentHashMap. – Nitram

0

Từ ConcurrentHashMap javadoc:

hoạt động Retrieval (bao gồm get) thường không chặn, vì vậy có thể chồng chéo với các hoạt động cập nhật (kể cả đặt và gỡ bỏ). Retrievals phản ánh kết quả của các hoạt động cập nhật mới nhất được hoàn thành khi họ khởi động. Đối với các phép toán tổng hợp như putAll và rõ ràng, các lần truy xuất đồng thời có thể phản ánh việc chèn hoặc loại bỏ chỉ một số mục nhập. Tương tự, các Iterator và Enumerations trả về các phần tử phản ánh trạng thái của bảng băm tại một số điểm tại hoặc từ khi tạo ra vòng lặp/liệt kê. Họ không ném ConcurrentModificationException. Tuy nhiên, các trình vòng lặp được thiết kế chỉ được sử dụng bởi một luồng tại một thời điểm.

Một điểm cần làm nổi bật là Iterator sẽ không phản ánh các thay đổi được thực hiện sau khi Iterator được tạo. Vì vậy, nếu bạn cần lặp lại các giá trị của bản đồ, trong khi các chủ đề khác đang thêm vào bản đồ và bạn quan tâm đến trạng thái hiện tại nhất của bản đồ, thì việc sử dụng ConcurrentHashMap có thể không thực hiện được bản đồ mà bạn cần.

+1

Cảm ơn bạn đã dọn dẹp. Nó trông tốt hơn! – bombe

+0

'Collections.synchronizedMap' dường như đồng bộ hóa ** tất cả truy cập **. Tại sao lựa chọn thiết kế đó trong 'ConcurrentHashMap'? Biến số – Dici

1

Bằng trực giác, một ConcurrentHashMap sẽ hoạt động giống như một tập các biến dễ bay hơi; các khóa bản đồ là các địa chỉ biến. get(key)put(key, value) sẽ hoạt động như đọc và ghi dễ bay hơi.

Điều đó không được nêu rõ trong tài liệu. Tuy nhiên, tôi tin chắc rằng đó là trường hợp. Nếu không, sẽ có rất nhiều hành vi bất ngờ, đáng ngạc nhiên làm suy yếu logic ứng dụng. Tôi không nghĩ Doug Lea sẽ làm điều đó với chúng tôi. Để chắc chắn, ai đó vui lòng hỏi anh ấy theo số concurrency-interest danh sách gửi thư.

Giả sử nó không tuân theo ngữ nghĩa không ổn định, chúng ta có thể lý do dựa trên Java Memory Model -

Tất cả biến động đọc và viết thành một tổng số thứ tự duy nhất. Điều này có thể được coi là một dòng thời gian giả, nơi đọc/ghi là điểm trên đó.

Đọc dễ bay hơi thấy ghi dễ bay hơi trước ngay lập tức và chỉ thấy ghi đó. "Trước" ở đây là theo dòng thời gian giả.

Dòng thời gian giả có thể khác với dòng thời gian "thực". Tuy nhiên, về lý thuyết, một ghi dễ bay hơi không thể bị trì hoãn vô hạn trên dòng thời gian giả. Và, trong pracitce, hai dòng thời gian là khá gần.

Vì vậy, chúng tôi có thể chắc chắn rằng, một ghi dễ bay hơi sẽ trở thành hiển thị "rất nhanh" để đọc.

+0

... 'biến động '... Thực ra, nó _is_ được ghi trong hợp đồng API' ConcurrentHashMap', nhưng không phải trong các từ đó. Javadoc nói, "... một hoạt động cập nhật cho một khóa nhất định mang một mối quan hệ _happens-before_ với bất kỳ truy xuất nào (không null) cho khóa đó." Về cơ bản, nó giống như cách 'volatile' được mô tả trong JLS: Một bản cập nhật cho một trường' volatile' thiết lập _happens-before_ với bất kỳ lần đọc tiếp theo nào của cùng một trường. –

+0

@jameslarge - vâng, nhưng đó chỉ là một phần của ngữ nghĩa dễ bay hơi. chúng tôi cũng cần 'đồng bộ hóa thứ tự' và [nhất quán đồng bộ hóa đơn đặt hàng] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.7) – ZhongYu

+0

có lẽ một câu hỏi hay hơn là, các hoạt động 'ConcurrentHashMap' * tuần tự nhất quán". Tôi đoán nó phải là, hoặc ít nhất, mọi người cho rằng nó được cấp. – ZhongYu

Các vấn đề liên quan