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 节省一些时间将是加速它的最好方法反正。如果您需要查看 synchronizeddao.* 调用是否是问题所在,您可以取出 dao 调用并替换为直接赋值。

尝试改用可变整数。也许我在这里遗漏了一些东西,但我在这里没有看到 AtomicReference 的用例。