2011-03-28 66 views
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>(); 
} 

回答

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

*“我不认为持有人应该扩展它正在包装的类型。” - - 我也不是!这不是我,它是日食... – maaartinus 2011-03-28 16:51:52