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