java - 用于任意可克隆数据的线程安全持有者

标签 java thread-safety atomicreference

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

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>();
}

最佳答案

由于clone()比synchronized要昂贵得多,因此从性能角度来看它几乎不重要。

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

唯一的区别是您可以执行此操作的第一个示例。 (无论你喜欢与否;)

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

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

编辑:一种对 GC 更友好的方法是使用以下方法。您可以编写 copyFrom() ,这样就不会创 build 置或获取数据的对象。

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);
    }
}

关于java - 用于任意可克隆数据的线程安全持有者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5462150/

相关文章:

java - Java AtomicReference#getAndSet 的用例是什么?

java - 避免线程已启动异常(Android)

java - 对可变对象的 AtomicReference 和可见性

java - 原子引用

java - 静态方法还是性能方面的单例(Android)?

objective-c - 从另一个线程调用 setter 时读取实例变量是否是线程安全的?

android - 检查服务器上是否存在 URL

java - 使用 2 个按钮启动和停止 JavaFX 后台线程

Java - 读取文件并加载到 HashMap - 如何减少时间?

java - 使用 gradle 时为 "java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper"