0

我有一个SomeMutableData带有公共clone()方法的类。我想确保没有线程看到不一致的状态(假设实例将仅使用持有者传递)。我认为使用同步是最安全的方法,对吧?

public final class ThreadSafeHolder {
    public ThreadSafeHolder(SomeMutableData data) {
        storeData(data);
    }

    public synchronized SomeMutableData cloneData() {
        return data.clone();
    }
    public synchronized void storeData(SomeMutableData data) {
        this.data = data.clone();
    }

    private SomeMutableData data;
}

以下方法与第一种方法一样安全吗?

public final class ThreadSafeHolder2 {
    public ThreadSafeHolder2(SomeMutableData data) {
        storeData(data);
    }

    public SomeMutableData cloneData() {
        return data.get().clone();
    }
    public void storeData(SomeMutableData data) {
        this.data.set(data.clone());
    }

    private final AtomicReference<SomeMutableData> data
        = new AtomicReference<SomeMutableData>();
}
4

1 回答 1

2

由于 clone() 比同步的成本高得多,所以从性能的角度来看它几乎不重要。

然而,第二个示例是线程安全的,并且速度稍快。

唯一的区别是第一个例子你可以这样做。(不管你喜欢与否;)

synchronized(theHolder) {
    SomeMutableData smd = theHolder.cloneData();
    smd.updateIt();
    theHolder.storeData(smd);
}

顺便说一句:我认为持有人不应该扩展它所包装的类型。

编辑:更 GC 友好的方法是使用以下方法。您可以编写 copyFrom() 以便在设置或获取数据时不创建任何对象。

public final class ThreadSafeHolder {
    private final SomeMutableData data = new SomeMutableData();

    public ThreadSafeHolder(SomeMutableData data) {
        copyFrom(data);
    }

    public synchronized void copyTo(SomeMutableData data) {
        data.copyFrom(this.data);
    }

    public synchronized void copyFrom(SomeMutableData data) {
        this.data.copyFrom(data);
    }
}
于 2011-03-28T16:44:13.927 回答