2013-08-29 33 views
14

Kiến thức của tôi về nội bộ JVM là nếu tham chiếu không được xuất bản chính xác, có khả năng các luồng khác nhau sẽ thấy các giá trị khác nhau của cùng một trường.Spring có xuất bản đậu theo cách an toàn không?

Câu hỏi của tôi là: Thùng chứa đậu mùa xuân có đảm bảo xuất bản an toàn không? Nếu không, tôi có nên làm tất cả các getters và setters đậu của tôi synchronized hoặc sử dụng volatile? Hoặc có thể sử dụng các trường final và khởi tạo hàm tạo?

Tôi giả định rằng điều này chỉ có thể là một vấn đề đối với đậu đơn vì đậu nguyên mẫu được tạo theo yêu cầu từ yêu cầu chuỗi. Tôi hiểu có đúng không?

Trả lời

10

Như Evgeniy đã nêu, việc khởi tạo ngữ cảnh ứng dụng xảy ra trong một chuỗi đơn lẻ. Do đó, câu trả lời cho câu hỏi của bạn không liên quan gì đến nội bộ của Spring mà là các chi tiết đồng bộ hóa giữa chuỗi tạo ngữ cảnh và chuỗi hoặc chủ đề sử dụng ngữ cảnh khi nó được tạo.

Mô hình bộ nhớ Java dựa trên happens-before relation (Đặc tả ngôn ngữ Java, §17.4.5) được xác định bởi các quy tắc khác nhau. Ví dụ: cuộc gọi tới Thread.start được thực hiện trong một chuỗi để bắt đầu một chủ đề mới xảy ra trước khi tất cả các hành động trong chính chuỗi mới được bắt đầu. Vì vậy, nếu chủ đề chính của ứng dụng của bạn đầu tiên tạo ra một ngữ cảnh ứng dụng, và sau đó bắt đầu các luồng khác để xử lý, thì các luồng xử lý được đảm bảo để xem ngữ cảnh được khởi tạo đầy đủ.

Fields đánh dấu volatile cũng áp đặt một xảy ra-trước mối quan hệ, theo nghĩa rằng nếu thread viết một giá trị cho một volatile, bất kỳ chủ đề khác mà nhìn thấy kết quả của việc ghi đó cũng được đảm bảo để xem bất cứ điều gì khác mà thread A đã làm trước nó đã viết dễ bay hơi. Do đó nếu không có bất kỳ đồng bộ hóa rõ ràng nào giữa chuỗi khởi tạo và chuỗi xử lý thì mẫu sau sẽ đủ để đảm bảo an toàn

public class Setup { 
    private volatile boolean inited = false; 

    private ApplicationContext ctx; 

    public boolean isInited() { return inited; } 

    public ApplicationContext getContext() { return ctx; } 

    public void init() { 
    ctx = new ClassPathXmlApplicationContext("context.xml"); 
    inited = true; // volatile write 
    } 
} 

public class Processor { 
    private void ensureInit() { 
    while(!setup.isInited()) { // volatile read 
     Thread.sleep(1000); 
    } 
    } 

    public void doStuff() { 
    ensureInit(); 
    // at this point we know the context is fully initialized 
    } 
} 
+0

Nó không cần thiết. Nếu bạn lo lắng về nó, hãy gắn cờ ngữ cảnh tự nó dễ bay hơi. – lscoughlin

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