任意可复制数据的线程安全持有者
问题描述:
我有一个类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>();
}
答
由于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);
}
}
*“我不认为持有人应该扩展它正在包装的类型。” - - 我也不是!这不是我,它是日食... – maaartinus 2011-03-28 16:51:52