【问题标题】:Is it possible to use the result of the last calculation directly ? Java Synchronized block是否可以直接使用上次计算的结果? Java 同步块
【发布时间】:2022-01-11 11:32:17
【问题描述】:

为什么Synchronized block在连续两次请求分解同一个值时可以直接使用之前的计算结果?

Java Concurrency in Practice 2-8 的代码

    public class two_8_CachedFactorizer  implements Servlet {
    @GuardedBy("this") private BigInteger lastNumber;
    @GuardedBy("this") private BigInteger[] lastFactors;
    @GuardedBy("this") private long hits;
    @GuardedBy("this") private long cacheHits;

    public synchronized long getHits(){return hits;}
    public synchronized double getCacheHitRatio(){
        return (double) cacheHits/(double)hits;
    }
    @Override
    public  void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        BigInteger i=extractFromRequest(req);
        BigInteger[] factors=null;
        synchronized (this) {
            ++hits;
            if (i.equals(lastNumber)) {
                ++cacheHits;
                factors = lastFactors.clone();
            }
        }
            if (factors==null)
            {
                factors=factor(i);//question in here :Suppose two identical requests arrive here at the same time
                synchronized (this)
                {
                    lastNumber=i;
                    lastFactors=factors.clone();
                }
            }
            encodeIntoResponse(res,factors);
        }

}

【问题讨论】:

  • 您的问题到底是什么?如果您希望一个线程等待另一个线程,因为它们都计算相同的值,那么在您提到的书中; Future 会有这样的实现。
  • lastFactorscacheHits等在哪里定义?请发帖minimal reproducible example

标签: java multithreading java.util.concurrent


【解决方案1】:

我相信您手头上至少有一个比赛条件。可能是较早发布的factor(i) 在稍后发布的factor(i) 之后完成;覆盖后来发布的factor(i) 的值。所以 lastFactor 和 lastNumber 可以更新到较早的版本。为了解决这个问题,我会在最后一个同步块中添加一些检查。

在当前代码中,您可以让多个线程执行相同的计算。我不确定这是否可取。

【讨论】:

  • 谢谢你,先生,当两个请求包含相同的“i”时,factor()会发生重复计数吗?假设这个“i”以前从未出现过
  • 如果先发出 i=10 再发出 i=1000。如果 i=1000 在 i=10 之前完成,lastNumber 将变为 10 而不是 1000。
  • 我不熟悉您的要求。但是如果你想缓存这些值,我会使用一个以'i'作为键和一个 CompletableFuture 作为值的 ConcurrentMap。但要小心让缓存无限制地增长。
  • 代码的目的似乎并不高效或“正确”(无论在这种情况下可能意味着什么)。它似乎只是缓存了最后一个计算,可以在多个线程上执行相同的计算或缓存任何因子(不仅仅是最大的)。我假设这是一个 JCIP 示例“这是如何以一种奇怪的错误方式执行多线程操作”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-12
  • 2017-09-29
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多