我正在实现一个简单的缓存,并将缓存存储为 AtomicReference。
private AtomicReference<Map<String, String>> cacheData;
应该从数据库表中(延迟地)填充缓存对象。
我提供了一种将缓存数据返回给调用者的方法,但如果数据为空(即未加载),则代码需要从数据库加载数据。为了避免同步,我想到了使用 compareAndSet() 方法:
public Object getCacheData() {
cacheData.compareAndSet(null, getDataFromDatabase()); // atomic reload only if data not set!
return Collections.unmodifiableMap(cacheData.get());
}
以这种方式使用 compareAndSet 是否可以,即。将数据库调用作为原子操作的一部分?它比仅同步方法更好/更坏吗?
非常感谢任何建议..
最佳答案
您没有达到预期的行为。这个表达式:
cacheData.compareAndSet(null, getDataFromDatabase())
将总是首先调用getDataFromDatabase()
。这意味着数据是否被缓存并不重要。如果是,您仍然调用数据库,但丢弃结果。缓存在工作,但性能同样很差。
考虑一下:
if(cacheData.get() == null) {
cacheData.compareAndSet(null, unmodifiableMap(getDataFromDatabase()));
}
return cacheData.get());
它并不完美(仍然可以在开始时多次调用 getDataFromDatabase()
),但稍后会按预期工作。此外,我之前移动了 Collections.unmodifiableMap()
,这样您就不必一遍又一遍地包装同一张 map 。
这让我们实现了更简单的实现(不需要 synchronized
或 AtomicReference
):
private volatile Map<String, String> cacheData;
if(cacheData == null) {
cacheData = unmodifiableMap(getDataFromDatabase());
}
return cacheData;
关于java - 使用 AtomicReference.compareAndSet 设置对数据库调用结果的引用是否合适?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12992478/