2012-01-14 34 views
12

Đọc trang web này, tôi đã tìm thấy this:Tại sao biến cuối cùng tĩnh này trong một chuỗi an toàn đơn lẻ?

[The] dòng private static final Foo INSTANCE = new Foo(); chỉ thực hiện khi lớp được thực tế sử dụng, điều này sẽ chăm sóc của các instantiation lười biếng, và nó đảm bảo được đề an toàn.

Tại sao chuỗi này được đảm bảo an toàn? Bởi vì trường này là final? Hoặc vì một lý do nào khác?

Trả lời

21

Vì nó là cuối cùng, vâng. Biến cuối cùng có ngữ nghĩa chủ đề an toàn đặc biệt, trong đó các chủ đề khác được đảm bảo để xem trường cuối cùng trong ít nhất là trạng thái khi nó được xây dựng.

Đây là số JLS 17.5, mặc dù ngôn ngữ có chút dày đặc. Các ngữ nghĩa này được giới thiệu trong Java 1.5, cụ thể là JSR-133. Xem trang này để biết một cuộc thảo luận không cụ thể về JSR-133 và các tác động khác nhau của nó.

Lưu ý rằng nếu bạn sửa đổi cá thể sau hàm tạo của nó, đó là không phải là nhất thiết phải là chuỗi an toàn. Trong trường hợp đó, bạn phải thực hiện các biện pháp phòng ngừa an toàn chủ đề thông thường để đảm bảo xảy ra trước các cạnh.

Tôi khá chắc chắn (mặc dù không hoàn toàn 100%) rằng thực tế chỉ có một luồng khởi tạo lớp là không phải là một yếu tố ở đây. Đúng là lớp chỉ được khởi tạo bởi một luồng, nhưng tôi không tin rằng có bất kỳ điều gì xảy ra cụ thể trước khi các cạnh được thiết lập giữa chuỗi đó bất kỳ chuỗi nào khác sử dụng lớp đó (trừ chuỗi khác không phải khởi tạo lại lớp). Vì vậy, không có từ khóa final, một chuỗi khác sẽ có thể thấy một thể hiện được tạo một phần của đối tượng. Cụ thể xảy ra trước khi các cạnh JMM định nghĩa là trong JLS 17.4.5, và khởi tạo lớp không được liệt kê ở đó.

+0

vâng, cảm ơn bạn. Câu trả lời tuyệt vời – MyTitle

+0

Tôi tin rằng lý do quan trọng hơn cuối cùng là khởi tạo lớp (khởi tạo tĩnh) phải được đồng bộ hóa và thread an toàn. Nó bằng cách sử dụng đồng bộ hóa thiết lập xảy ra-trước khi đặt hàng. Xem 12.4.2 (http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4.2) để biết thêm chi tiết. – sjlee

+0

@sjlee Đúng là khởi tạo yêu cầu khóa, nhưng nếu luồng A khởi tạo MyClass, và chuỗi B đến khoảng 5 phút sau và sử dụng MyClass, chuỗi B sẽ không cố gắng khởi tạo MyClass (vì nó đã được khởi tạo). Điều đó có nghĩa là nó sẽ không có khóa trên 'MyClass.class', điều đó có nghĩa là không có mối quan hệ xảy ra - trước nào giữa các hành động của luồng A và luồng B. Nếu mỗi luồng đã khóa trên 'MyThread.class' bất cứ khi nào nó sử dụng nó, bạn sẽ không bao giờ cần phải thiết lập bất kỳ mối quan hệ nào xảy ra trước đó. – yshavit

2

Khối khởi tạo tĩnh của bất kỳ lớp nào được đảm bảo là chuỗi đơn. Một singleton đơn giản hơn là sử dụng một enum

enum Singleton { 
    INSTANCE; 
} 

Đây cũng là chủ đề an toàn và lớp được khởi tạo lười biếng.

+0

Tham chiếu cho điều này, ví dụ: JLS? – paislee

+0

@paislee: Tôi đang ở nhà nhiều hơn trong JVMS nên tôi có thể cung cấp cho bạn [tham chiếu đến] (http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc. html # 24237). Nếu bạn làm theo các thủ tục bạn thấy rằng khởi tạo lớp chỉ có thể được thực hiện bởi một sợi đơn (mỗi bộ nạp lớp). Trình khởi tạo tĩnh được gọi trong bước 8. – musiKk

+1

Các JVMS cung cấp ngữ nghĩa chặt chẽ hơn JLS theo nhiều cách khác nhau, do đó, nó không phải là một nguồn tuyệt vời cho tính chính xác ngôn ngữ chung. JLS định nghĩa khởi tạo lớp trong [JLS 12.4] (http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4) và 12.4.2 chi tiết thủ tục cụ thể. – yshavit

3

Nó được đảm bảo là luồng an toàn vì JVM đảm bảo rằng các bộ khởi tạo tĩnh được thực hiện trên một chuỗi đơn. Nó không có nghĩa là trường hợp của Foo là chủ đề an toàn trong nội bộ - nó chỉ có nghĩa là bạn được đảm bảo rằng hàm tạo của Foo sẽ được gọi chính xác một lần, trên một sợi, thông qua đường dẫn mã cụ thể này.

5

constructor của lớp cha và initializers tĩnh/Chẳng hạn được đảm bảo để được thực thi nguyên tử và từ private static final FOO INSTANCE = new FOO; tương đương với

private static final FOO INSTANCE; 

static{ 
    INSTANCE = new FOO(); 
} 

trường hợp này rơi vào thể loại trên.

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