Tôi đọc trong "Java Concurrency In Practice" rằng "xuất bản các đối tượng trước khi chúng được xây dựng hoàn toàn có thể thỏa hiệp an toàn luồng". Ai đó có thể giải thích điều này?xuất bản các đối tượng và an toàn chủ đề
Trả lời
toán tử mới được phép trả lại giá trị trước khi hàm tạo của lớp kết thúc. Vì vậy, một biến có thể không đọc null nhưng chứa một cá thể lớp chưa được khởi tạo. Điều này xảy ra do sắp xếp lại byte.
Một số làm rõ: Từ góc độ chủ đề đơn lẻ, JVM được phép sắp xếp lại một số lệnh. Khi tạo một thể hiện truyền thống bạn sẽ nghĩ nó đi như thế này:
- cấp phát bộ nhớ
- chạy khởi tạo (constructor)
- assign tham chiếu đến var
Trong khi trên thực tế JVM có thể làm một cái gì đó như:
- cấp phát bộ nhớ
- assign tham chiếu đến var
- chạy khởi (constructor)
này có ưu điểm hiệu suất kể từ địa chỉ không cần phải được tra cứu lên một lần nữa. Từ một quan điểm chuỗi đơn lẻ, điều này không thay đổi thứ tự của logic. Chương trình của bạn hoạt động tốt. Nhưng điều này đặt ra một vấn đề trong mã đa luồng. Điều này có nghĩa là tham chiếu có thể được xuất bản trước khi hàm tạo đã chạy. Do đó bạn cần một quy tắc 'xảy ra-trước' để đảm bảo rằng cá thể được khởi tạo hoàn toàn. Khai báo các biến volatile dos thực thi các quy tắc xảy ra trước đó.
Thông tin thêm về sắp xếp lại: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering
xem xét mã này:
public class World{
public static Point _point;
public static void main(String[] args){
new PointMaker().start();
System.out.println(_point);
}
}
public class Point{
private final int _x, _y;
public Point(int x, int y){
_x = x;
World._point = this;//BAD: publish myself before I'm fully constructed
//some long computation here
_y = y;
}
public void toString(){
return _x + "," + _y;
}
}
public class PointMaker extends Thread{
public void run(){
new Point(1, 1);
}
}
Vì Point
xuất bản bản thân trước khi thiết lập giá trị của _y
, cuộc gọi đến println
có thể mang lại "1,0"
thay vì dự kiến "1,1"
.
(Lưu ý rằng nó cũng có thể mang lại "null"
nếu PointMaker
+ Point.<init>
không nhận được đủ xa để thiết lập các lĩnh vực World._point
trước khi cuộc gọi đến println
thực thi.)
Để chính xác, thậm chí có thể in "0,0". Nếu chúng ta rò rỉ tham chiếu này từ hàm tạo, thì JLS không thực hiện bất kỳ sự đảm bảo nào về kết quả cuối cùng. – Voo
- 1. Đối tượng 'an toàn chủ đề' có nghĩa là gì?
- 2. QueryPerformanceCounter và an toàn chủ đề
- 3. an toàn Chủ đề và các biến địa phương
- 4. Java StringBuilder và An toàn Chủ đề
- 5. An toàn chủ đề và `const`
- 6. Chủ đề NSPersistentStoreCoordinator có an toàn không?
- 7. Chủ đề an toàn chủ đề - tĩnh hay không?
- 8. Tại sao chủ đề EJBs an toàn và servlet không?
- 9. Chủ đề này có an toàn không?
- 10. Ngăn xếp C++ an toàn Chủ đề
- 11. An toàn chủ đề và System.Text.Encoding trong C#
- 12. lucene thực hành tốt và an toàn chủ đề
- 13. Sự khác nhau giữa đề an toàn và an toàn
- 14. Ruby/Rails an toàn chủ đề
- 15. An toàn Chủ đề với Thẻ Mẫu
- 16. An toàn chủ đề của JTextArea.append
- 17. Chủ đề NSFileManager có an toàn không?
- 18. an toàn Chủ đề trong C mảng #
- 19. Chủ đề libuv có an toàn không?
- 20. Chủ đề an toàn unique_ptr di chuyển
- 21. Chủ đề an toàn trong F #
- 22. Cách tạo chủ đề an toàn EntityManagerFactory?
- 23. Cách kiểm tra an toàn chủ đề
- 24. An toàn chủ đề của SocketOutputStream
- 25. Chủ đề java.util.Hashtable có an toàn không?
- 26. Chủ đề MSMQ có an toàn không?
- 27. Python 2.7: In chủ đề an toàn
- 28. Xóa mảng an toàn chủ đề
- 29. Perl Chủ đề Mô-đun an toàn
- 30. NHibernate an toàn chủ đề với phiên
bạn có thể trích dẫn một nguồn? – musiKk
@musiKk câu hỏi hay, tìm kiếm nó. –
Tôi đã nghĩ rằng, thay vì điều này, tham chiếu có thể nói về việc xuất bản đối tượng bên trong hàm tạo (hoặc cái gì đó mà nó gọi). Tôi không thể nghĩ ra một trường hợp mà toán tử mới trả về một tham chiếu đối tượng trước khi hàm tạo được gọi là hoàn thành. – arcy