使用AtomicReference.compareAndSet设置对数据库调用结果的引用是否合适? [英] Is it appropriate to use AtomicReference.compareAndSet to set a reference to the results of a database call?

查看:105
本文介绍了使用AtomicReference.compareAndSet设置对数据库调用结果的引用是否合适?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个简单的缓存,该缓存存储为AtomicReference.

I am implementing a simple cache with the cache stored as an AtomicReference.

private AtomicReference<Map<String, String>> cacheData;

应该从数据库表中(延迟地)填充缓存对象.

The cache object should be populated (lazily) from a database table.

我提供了一种将缓存数据返回给调用者的方法,但是如果数据为空(即未加载),则代码需要从数据库加载数据.为了避免同步,我想到了使用compareAndSet()方法:

I provide a method to return the cache data to a caller, but if the data is null (ie. not loaded), then the code needs to load the data from the database. To avoid synchronized I thought of using the compareAndSet() method:

public Object getCacheData() {
  cacheData.compareAndSet(null, getDataFromDatabase()); // atomic reload only if data not set!
  return Collections.unmodifiableMap(cacheData.get());
}

可以以这种方式使用compareAndSet吗?涉及数据库调用作为原子动作的一部分?比同步方法更好/更糟糕吗?

Is it ok to use compareAndSet in this way ie. to involve a database call as part of the atomic action? Is it any better/worse than just synchronizing the method?

非常感谢您的任何建议.

Many thanks for any advice..

推荐答案

您没有实现预期的行为.表达式:

You do not achieve expected behaviour. This expression:

cacheData.compareAndSet(null, getDataFromDatabase())

始终首先呼叫getDataFromDatabase().这意味着是否缓存了数据都没有关系.如果是这样,您仍然可以调用数据库,但是放弃结果.缓存正在运行,但是性能同样很差.

will always call getDataFromDatabase() first. This means that it doesn't matter if the data was cached or not. If it was, you still call the database, but discard the results. The cache is working, but the performance is equally poor.

请改用此方法:

if(cacheData.get() == null) {
    cacheData.compareAndSet(null, unmodifiableMap(getDataFromDatabase()));
}
return cacheData.get());

这不是完美的方法(仍然可以在开始时多次调用getDataFromDatabase()),但稍后会按预期工作.另外,我早些时候移动了Collections.unmodifiableMap(),这样您就不必一遍又一遍地包装同一张地图.

It's not perfect (still getDataFromDatabase() can be called multiple times at the beginning), but will work later as expected. Also I moved Collections.unmodifiableMap() earlier so that you don't have to wrap the same map over and over again.

这使我们实现了更简单的实现(不需要synchronizedAtomicReference):

Which brings us to even simpler implementation (no synchronized or AtomicReference needed):

private volatile Map<String, String> cacheData;

if(cacheData == null) {
  cacheData = unmodifiableMap(getDataFromDatabase());
}
return cacheData;

这篇关于使用AtomicReference.compareAndSet设置对数据库调用结果的引用是否合适?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆