2010-04-05 32 views
41

Mô hình bộ nhớ java yêu cầu viết int là nguyên tử: Tức là, nếu bạn viết giá trị cho nó (bao gồm 4 byte) trong một luồng và đọc nó trong một chuỗi khác, bạn sẽ nhận được tất cả các byte hoặc không có, nhưng không bao giờ 2 byte mới và 2 byte cũ hoặc như vậy.Viết một tham chiếu nguyên tử trên các máy ảo 64 bit

Điều này không được đảm bảo cho long. Ở đây, viết 0x1122334455667788 vào một biến giữ 0 trước khi có thể dẫn đến một chuỗi khác đọc 0x112233440000000 hoặc 0x0000000055667788.

Hiện tại, đặc điểm kỹ thuật không yêu cầu tham chiếu đối tượng là int hoặc dài. Vì lý do an toàn loại, tôi nghi ngờ rằng chúng được đảm bảo bằng văn bản về mặt nguyên tử, nhưng trên máy ảo 64 bit, các tham chiếu này có thể là các giá trị 64 bit (chỉ là địa chỉ bộ nhớ).

Bây giờ đây là những câu hỏi của tôi:

  • Có bất kỳ thông số kỹ thuật mô hình bộ nhớ bao gồm này (mà tôi đã không tìm thấy)?
  • Nghi ngờ viết lâu là nguyên tử trên máy ảo 64 bit?
  • Máy ảo có bị buộc phải ánh xạ tham chiếu đến 32 bit không?

Kính trọng, Steffen

+2

@Steffen Heil: soi mói nhưng lưu ý rằng không phải tất cả tài liệu tham khảo là 64 bit trong nội bộ thậm chí trên 64 bit VM (do số lượng đáng kinh ngạc của sự lãng phí 64 bit tài liệu tham khảo được tạo ra).Các máy ảo hiện đại đang sử dụng nén con trỏ/nén tham chiếu có tên * "CompressedOops" *: http://wikis.sun.com/display/HotSpotInternals/CompressedOops Vì vậy, tôi không đồng ý rằng chúng * có thể * có giá trị 64 bit nhưng chúng thường 't (không phải là nó thay đổi nhiều đến câu trả lời mà Dirk đăng). – SyntaxT3rr0r

Trả lời

52

Xem JLS section 17.7: Non-atomic Treatment of double and long

Theo mục đích của mô hình bộ nhớ ngôn ngữ lập trình Java, một ghi duy nhất để một giá trị dài hoặc đôi non-volatile được coi là hai ghi riêng: một đến mỗi nửa 32 bit. Điều này có thể dẫn đến tình huống trong đó chuỗi thấy 32 bit đầu tiên của giá trị 64 bit từ một ghi và 32 bit thứ hai từ một lần ghi khác.

Ghi và đọc các giá trị dài và kép dễ bay hơi luôn là nguyên tử.

Ghi và đọc tham chiếu luôn là nguyên tử, bất kể liệu chúng có được triển khai dưới dạng giá trị 32 bit hoặc 64 bit hay không.

Một số triển khai có thể thấy thuận tiện khi chia một hành động đơn trên giá trị dài hoặc dài 64 bit thành hai hành động ghi trên giá trị 32 bit liền kề. Vì lợi ích của hiệu quả, hành vi này là thực hiện cụ thể; việc thực hiện Máy ảo Java là miễn phí để thực hiện ghi các giá trị dài và kép một cách nguyên tử hoặc trong hai phần.

Việc triển khai Máy ảo Java được khuyến khích tránh chia các giá trị 64 bit nếu có thể. Các lập trình viên được khuyến khích để tuyên bố các giá trị 64 bit được chia sẻ là dễ bay hơi hoặc đồng bộ hóa các chương trình của chúng một cách chính xác để tránh các biến chứng có thể xảy ra.

(Nhấn mạnh thêm)

+0

Ok, tôi đã bỏ lỡ điểm trong thông số kỹ thuật một lần nữa. Dường như với tôi, tôi quá mệt mỏi và nên ngủ thay vì đặt câu hỏi ... Cảm ơn con trỏ. (AGAIN) –

+1

Nếu "Ghi và đọc tài liệu tham khảo luôn là nguyên tử, bất kể chúng được thực hiện dưới dạng giá trị 32 hay 64 bit.", Tại sao chúng ta có lớp AtomicReference (https://docs.oracle.com/javase/ 7/docs/api/java/util/đồng thời/nguyên tử/AtomicReference.html)? Chỉ vì phương thức getAndSet/compareAndSet? –

+0

Không thấy giá trị tham chiếu bị rách chỉ là một phần của hình ảnh. 'AtomicReference' tồn tại chủ yếu cho API đồng bộ hóa của nó (' compareAndSet' mà bạn ám chỉ), @ mc.android.developer, và không có "chỉ" ở đây. Đó thực sự là phần quan trọng. – Dirk

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