2012-04-24 30 views
5

Tôi có một lớp hàngĐây có phải là ấn phẩm an toàn của đối tượng không?

class Item { 
    public int count; 
    public Item(int count) { 
    this.count = count; 
    } 
} 

Sau đó, tôi sẽ đặt một tham chiếu đến mục trong một lĩnh vực của lớp khác

class Holder { 
    public Item item; 
    public Holder() { 
    item = new Item(50); 
    } 
} 

mới đối tượng mục này có thể được công bố một cách an toàn? Nếu không, tại sao? Theo Java Concurrency trong Thực hành, mục mới được xuất bản mà không được xây dựng hoàn toàn, nhưng theo ý kiến ​​của tôi, mục mới được xây dựng hoàn toàn: tham chiếu this không thoát và tham chiếu đến nó và trạng thái của nó được xuất bản ở cùng một thời gian, do đó, chuỗi tiêu thụ sẽ không thấy giá trị cũ. Hay là vấn đề hiển thị. Tôi không biết chính xác lý do.

+0

Bài viết thú vị về DW về chủ đề khám phá nhiều vấn đề liên quan đến đồng bộ hóa: http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html – maksimov

+0

Tôi rất tiếc, tôi đã quên nó! – ohyeahchenzai

Trả lời

13

Đối tượng mục mới này có thể được xuất bản một cách an toàn không? Nếu không, tại sao?

Vấn đề xoay quanh tối ưu hóa và sắp xếp lại hướng dẫn. Khi bạn có hai chủ đề đang sử dụng đối tượng được xây dựng mà không cần đồng bộ hóa, trình biên dịch có thể quyết định sắp xếp lại hướng dẫn về hiệu quả và phân bổ không gian bộ nhớ cho đối tượng và lưu trữ tham chiếu trong trường item trước trước khi kết thúc với hàm tạo và khởi tạo trường. Hoặc nó có thể sắp xếp lại bộ nhớ đồng bộ hóa để các chủ đề khác cảm nhận được theo cách đó.

Nếu bạn đánh dấu trường itemfinal thì hàm tạo được đảm bảo hoàn thành việc khởi tạo trường đó như một phần của hàm tạo. Nếu không, bạn sẽ phải đồng bộ hóa trên một khóa trước khi sử dụng nó. Đây là một phần của Java language definition.

Dưới đây là một vài tài liệu tham khảo:

+0

Có lẽ tôi nên đọc đặc tả ngôn ngữ java, cảm ơn bạn! – ohyeahchenzai

+0

Hãy để tôi chỉ cho bạn thẳng đến [chương.] Chính xác (http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4) Đó là một bài đọc tuyệt vời, nhiều không chỉ là đặc điểm kỹ thuật khô. –

+0

Cảm ơn @Marko. Tôi đã thêm liên kết đó vào câu trả lời của tôi. – Gray

5

Vâng, có một vấn đề tầm nhìn, như Holder.item không phải là final. Vì vậy, không có gì đảm bảo rằng một chuỗi khác sẽ thấy giá trị khởi tạo của nó sau khi việc xây dựng Holder hoàn tất.

Và khi @Gray chỉ ra, JVM được tự do sắp xếp lại hướng dẫn khi không có rào cản bộ nhớ (có thể được tạo bằng khóa (đồng bộ hóa), vòng loại final hoặc volatile). Tùy thuộc vào ngữ cảnh, bạn phải sử dụng một trong các mục này để đảm bảo xuất bản an toàn.

+0

Tôi nghĩ rằng tôi có thể nhận được câu trả lời, đó là việc sắp xếp lại, nhưng tôi không thực hiện đúng thứ tự, nhưng như Gray đã chỉ ra, tôi biết một số về nó, cảm ơn cả hai! – ohyeahchenzai

+0

@ohyeahchenzai Nếu bạn nghiên cứu cẩn thận chương này nếu JLS được đề cập trong câu trả lời khác, tất cả sẽ rõ ràng cho bạn. –

+0

Tuy nhiên, một lý do khác để ủng hộ bất biến bằng cách làm cho các trường cuối cùng. –

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