2011-08-22 28 views
6

Nếu nó là tất cả các trường, kể cả siêu trường, của một lớp java cuối cùng không thể thay đổi được '' để có thể an toàn luồng hoặc đủ để không có phương thức bổ trợ?các trường cuối cùng và an toàn luồng

Giả sử tôi có POJO với trường không phải cuối cùng trong đó tất cả các trường là loại của một số lớp không thể thay đổi. POJO này có các bộ định vị getters, và một hàm tạo mà thiết lập một số giá trị ban đầu. Nếu tôi mở rộng POJO này bằng cách loại bỏ các phương thức sửa đổi, do đó làm cho nó không thay đổi được, lớp mở rộng sẽ là an toàn luồng không?

+2

Bạn có ý nghĩa gì khi * loại bỏ các phương thức sửa đổi * phương pháp sửa đổi? Ném một ngoại lệ từ tất cả những người định cư? Điều này sẽ vi phạm [nguyên tắc thay thế Liskov] (http://en.wikipedia.org/wiki/Liskov_substitution_principle). Nhưng có, lớp này ** sẽ ** được an toàn thread. –

+0

Có, ném ngoại lệ thời gian chạy hoặc ghi đè chúng bằng một cơ thể trống có thể với một số lần ghi nhật ký. Tôi biết nó vi phạm LSP. – pcjuzer

Trả lời

11

Để sử dụng đối tượng không thay đổi hiệu quả mà không cần final trường theo cách an toàn, bạn cần sử dụng một trong các thành phần xuất bản an toàn khi tạo đối tượng cho các chủ đề khác sau khi khởi tạo. nhà nước (từ Java Concurrency in Practice):

  • Khởi tạo một tham chiếu đối tượng từ một initializer tĩnh;
  • Lưu trữ tham chiếu đến nó vào trường dễ bay hơi hoặc AtomicReference;
  • Lưu trữ tham chiếu đến trường đó vào trường cuối cùng của đối tượng được tạo đúng; hoặc
  • Lưu trữ tham chiếu đến trường đó vào trường được khóa cẩn thận.

lĩnh vực Tuyên bố của đối tượng bất biến của bạn như final phiên bản hạn chế này (ví dụ: nó đảm bảo rằng nếu đề khác nhìn thấy một tham chiếu đến đối tượng, họ cũng thấy final lĩnh vực của mình trong trạng thái khởi tạo đầy đủ). Tuy nhiên, trong trường hợp chung nó không đảm bảo rằng các chủ đề khác có thể thấy một tham chiếu đến đối tượng ngay sau khi nó được xuất bản, vì vậy bạn vẫn có thể cần phải sử dụng ấn phẩm an toàn để đảm bảo nó.

Lưu ý rằng nếu đối tượng của bạn thực hiện một giao diện, bạn có thể sử dụng một cách tiếp cận được sử dụng bởi Collections.unmodifiableList(), vv:

class ImmutableFooWrapper implements IFoo { 
    private final IFoo delegate; // final provides safe publication automatically 

    public ImmutableFooWrapper(IFoo delegate) { 
     this.delegate = delegate; 
    } 
    ... 
} 

public IFoo immutableFoo(IFoo foo) { 
    return new ImmutableFooWrapper(foo); 
} 
+0

Cảm ơn câu trả lời chi tiết của bạn. Tôi đã suy nghĩ về cùng một giải pháp với việc sử dụng đại biểu nhưng sau đó tôi luôn luôn quay trở lại giải pháp với phần mở rộng, bởi vì tôi đoán 'siêu' tham chiếu cũng là cuối cùng. Tôi nhớ gì? – pcjuzer

+0

@pcjuzer: 'super' không có gì để làm với đồng thời, do đó trong trường hợp của phần mở rộng, bạn sẽ cần xuất bản an toàn anyway. – axtavt

+0

Vì vậy, điều đó có nghĩa là nếu bạn đang khai báo một trường cuối cùng sau đó nếu nó đang được cập nhật bởi một sợi thì chuỗi khác sẽ không nhìn thấy nó và nếu nó thấy sau đó nó sẽ thấy trong trạng thái cập nhật? – AKS

-2

Có, nó sẽ không thay đổi và hậu quả là thread-safe nhưng chỉ miễn là các lĩnh vực là riêng tư.

+2

Tại sao các trường thực sự phải là riêng tư? – xSNRG

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