AtomicReference
的语义是什么? ?
如果我这样做:
AtomicReference<CustomObject> ref = new AtomicReference<CustomObject>();
然后我这样做:
public void someMethod(){
//do something
ref.set(loadNewData());
}
private final Sempahore updatePermit = new Sempahore(1);
private CustomObject loadNewData(){
CustomObject obj = null;
if (updatePermit.tryAcquire()) {
obj = ...; //do the loading and create Object
updatePermit.release();
} else {
//update already running, wait
updatePermit.acquire();
//release the permit immediately
updatePermit.release();
obj = ref.get(); //????
}
return obj;
}
是否有在线obj = ref.get(); //????
的保证 get
将返回 CustomObject
的最新最新版本?
这与 assylias 对 post 的回答有关。 :
最佳答案
实际上,您的代码存在竞争条件,可能会导致新数据丢失:
- 第一个调用者进入 loadNewData 并开始加载新数据(有信号量)
- 第二个调用者无法获取信号量并在获取时等待
- 第一个调用者完成加载并释放信号量(但尚未返回新数据)
- 第二个调用者获取信号量,调用
ref.get()
并获取旧数据 - 第一个调用者返回新数据并传递给
ref.set()
- 第二个调用者返回旧数据,该数据在传递给
ref.set()
时覆盖新数据
由于 someMethod()
总是加载新数据,并且您总是希望调用者在新数据加载时等待,所有这些额外的东西是没用的。只需在整个 block 周围使用一个简单的同步块(synchronized block)(或锁)并放弃原子引用。根据链接的帖子,似乎您只想执行一次此操作,因此请使用初始化标志。
private boolean _initialized;
public synchronized void loadLatestData() {
if(!_initialized) {
// load latest data ...
_initialized = true;
}
}
关于java - 原子引用的保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13362427/