Get/Set缓存中的值使用java中的AtomicReference
Get/Set the value in the cache using the AtomicReference in java
我已经在 codereview 网站 https://codereview.stackexchange.com/questions/158999/get-set-the-value-in-the-cache-using-the-atomicreference-in-java 上发布了这个问题,但我想在这里发布,这样它可以覆盖更广泛的受众,我也可以在这里发布它来获得更快的解决方案。
我有以下代码使用同步块在缓存中获取和设置数据,我想知道我是否可以优化以下代码:-
public int getValue() {
AtomicReferenceTest<Integer> cachedIntRef = new AtomicReference<Integer>();
boolean wasCached = true;
Integer cachedInt = cachedIntRef.get();
if (cachedInt == null) {
synchronized (cachedIntRef) {
cachedInt = cachedIntRef.get();
if (cachedInt == null) {
wasCached = false;
// Make DB call to get the data and update the cache.
cachedInt = baseDao.getCloudMaximumWeight();
cachedIntRef.set(cachedInt);
}
}
}
}
我想知道是否有任何方法可以删除 synchronized 块并进一步优化或者此代码已经优化?
编辑:- 如果我在任何站点上得到答案,我将从其中一个站点删除问题。此外,当我有时甚至在线程数较少的情况下分析我的应用程序时,我看到线程阻塞在 synchronized
段代码上。这让我觉得我的代码正在使用 AtomicRef
,我可以以某种方式摆脱 syncronized
或者是否有其他更好的方法来优化代码。
I want to know if is there is any way by which i can remove the synchronized block and optimize further or this code is already optimized?
我假设优化代码意味着删除 synchronized
块。这种想法的问题在于,您的 dao
通话很可能比 synchronized
贵 显着 。任何 IO(尤其是远程数据库)的成本至少比锁定高 4 个数量级。
也就是说,如果您不介意在初始化缓存时调用多个 DAO,则可以删除 synchronized
块。如果 DAO 调用成本低廉,那么使用 2 个线程进行调用可能不是问题。有一个竞争条件,一个人的答案将被放入缓存,但他们的结果很可能无论如何都是一样的。我经常这样做,并假设随着应用程序的启动,前几次调用会随着缓存变暖而变得更加昂贵。但是,2 个线程发出相同的 DAO 请求 ever 会比 1 个线程执行此请求而 1 个线程等待另一个线程完成要快吗?
如果有许多不同的 DAO 调用,那么您可以尝试某种锁隔离,这样并不是所有的缓存请求都经过同一个锁。这将允许一些并行化,这可能会有所帮助。我无法判断您的代码是特定的还是问题的示例。例如,ConcurrentHashMap
就是这样工作的。
但实际上我会确定这部分代码存在性能问题,然后再担心太多。即使分析器说它是一个主要的时间槽,也可能只是 DAO 调用是等式中最昂贵的部分,所以用 synchronization
节省一些时间将是加速它的最好方法反正。如果您需要查看 synchronized
或 dao.*
调用是否是问题所在,您可以取出 dao 调用并替换为直接赋值。
尝试改用可变整数。也许我在这里遗漏了一些东西,但我在这里没有看到 AtomicReference 的用例。
我已经在 codereview 网站 https://codereview.stackexchange.com/questions/158999/get-set-the-value-in-the-cache-using-the-atomicreference-in-java 上发布了这个问题,但我想在这里发布,这样它可以覆盖更广泛的受众,我也可以在这里发布它来获得更快的解决方案。
我有以下代码使用同步块在缓存中获取和设置数据,我想知道我是否可以优化以下代码:-
public int getValue() {
AtomicReferenceTest<Integer> cachedIntRef = new AtomicReference<Integer>();
boolean wasCached = true;
Integer cachedInt = cachedIntRef.get();
if (cachedInt == null) {
synchronized (cachedIntRef) {
cachedInt = cachedIntRef.get();
if (cachedInt == null) {
wasCached = false;
// Make DB call to get the data and update the cache.
cachedInt = baseDao.getCloudMaximumWeight();
cachedIntRef.set(cachedInt);
}
}
}
}
我想知道是否有任何方法可以删除 synchronized 块并进一步优化或者此代码已经优化?
编辑:- 如果我在任何站点上得到答案,我将从其中一个站点删除问题。此外,当我有时甚至在线程数较少的情况下分析我的应用程序时,我看到线程阻塞在 synchronized
段代码上。这让我觉得我的代码正在使用 AtomicRef
,我可以以某种方式摆脱 syncronized
或者是否有其他更好的方法来优化代码。
I want to know if is there is any way by which i can remove the synchronized block and optimize further or this code is already optimized?
我假设优化代码意味着删除 synchronized
块。这种想法的问题在于,您的 dao
通话很可能比 synchronized
贵 显着 。任何 IO(尤其是远程数据库)的成本至少比锁定高 4 个数量级。
也就是说,如果您不介意在初始化缓存时调用多个 DAO,则可以删除 synchronized
块。如果 DAO 调用成本低廉,那么使用 2 个线程进行调用可能不是问题。有一个竞争条件,一个人的答案将被放入缓存,但他们的结果很可能无论如何都是一样的。我经常这样做,并假设随着应用程序的启动,前几次调用会随着缓存变暖而变得更加昂贵。但是,2 个线程发出相同的 DAO 请求 ever 会比 1 个线程执行此请求而 1 个线程等待另一个线程完成要快吗?
如果有许多不同的 DAO 调用,那么您可以尝试某种锁隔离,这样并不是所有的缓存请求都经过同一个锁。这将允许一些并行化,这可能会有所帮助。我无法判断您的代码是特定的还是问题的示例。例如,ConcurrentHashMap
就是这样工作的。
但实际上我会确定这部分代码存在性能问题,然后再担心太多。即使分析器说它是一个主要的时间槽,也可能只是 DAO 调用是等式中最昂贵的部分,所以用 synchronization
节省一些时间将是加速它的最好方法反正。如果您需要查看 synchronized
或 dao.*
调用是否是问题所在,您可以取出 dao 调用并替换为直接赋值。
尝试改用可变整数。也许我在这里遗漏了一些东西,但我在这里没有看到 AtomicReference 的用例。