【问题标题】:A thread-safe holder for arbitrary cloneable data任意可克隆数据的线程安全持有者
【发布时间】:2011-03-28 16:35:09
【问题描述】:

我有一个带有公共 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>();
}

【问题讨论】:

    标签: java thread-safety atomicreference


    【解决方案1】:

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

    【讨论】:

    • “我认为持有者不应该扩展它正在包装的类型。” - 我也不!不是我,是日食……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 2021-01-31
    • 2019-06-27
    • 1970-01-01
    相关资源
    最近更新 更多