Java最终安全发布

时间:2013-11-04 09:05:30

标签: java multithreading visibility

只是为了确保。 我在实践书中遵循Java Concurrency。 当谈到安全发布时尤其是最终版本,我很清楚,首先引用将对所有其他线程可见,其次发布对象的状态对于任何其他线程是可见的,但这里的问题是如果状态是引用的数组元素保证在发布状态时可见? (当然,只要没有人修改这些数据对象)。

示例:

@Mutable
public class NotThreadsafeDataObject {

    private String message;

    public NotThreadsafeDataObject (String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

现在让我们安全地发布一系列可变对象:

public class Publish {

    public final NotThreadsafeDataObject[] publish;

    public Publish() {
        publish = new NotThreadsafeDataObject[] { new NotThreadsafeDataObject("one"), new NotThreadsafeDataObject("two")};

    }

}

2 个答案:

答案 0 :(得分:0)

如果我们用“Java Concurrency in Practice”中提到的术语来说话,那么你的数组就是一个“有效不可变”的对象。对于此类对象,始终需要安全发布,以免破坏内部状态。所以你的代码没问题,因为你正在使用安全的发布。更具体地说,“final”关键字内存语义保证访问final字段的线程将看到在字段写入之前发生的所有事情(“之前发生”)。

答案 1 :(得分:0)

我很确定您仍然可以修改Array中各个可变对象的值。即

publish[0].setMessaage("Hello");

会工作得很好。而且我相信你可以从数组中删除对象。它是不能更改的Array引用,因为它被声明为final。如果你想拥有完全不可变的集合,我会使用声明为final的List,然后创建一个新的单独List,填充它然后使用方法public static List unmodifiableList(List list)将它分配到你的最终列表:

ublic class Publish {

    public static final List<NotThreadsafeDataObject> publish;

    static {
        init();
    }  

    private static void synchronized init() {
       List<NotThreadsafeDataObject> list = new ArrayList<>();
       list.add(new NotThreadsafeDataObject("one");
       list.add(new NotThreadsafeDataObject("two");
       publish = Collections.unmodifiableList(list);
    }  
}

这使得防弹完全不可变的列表既不能改变它也不能改变它的内容。