【问题标题】:How to optimize the synchronized method in JavaJava中如何优化同步方法
【发布时间】:2019-11-13 06:31:53
【问题描述】:

我在我的应用程序中看到了这个遗留代码,它导致线程在生产中的 synchronized 方法上被阻塞。

private synchronized void productMapBuilder(List<Product> products) {
        Map<String, Set<Product>> map = new HashMap<>();
        for (Product product : products) {
            map.putAll(buildProductMap(product));// this call another method which isn't synchronised.
        }
        this.productsMap = map;
    }

现在,List&lt;product&gt; products 被传递给这个productMapBuilder,我知道它是一个线程特定的,线程之间唯一的共享变量是productsMap

那么我们真的需要将synchronized 放在整个方法上吗?

我也想不出任何其他方法来优化这个方法,因为我不是并发程序方面的专家,因此欢迎任何有价值的资源和建议:)

【问题讨论】:

  • Map&lt;String, Set&lt;Product&gt;&gt; productsMap = new HashMap&lt;&gt;(); 不在线程之间共享。它总是在调用此方法时创建。
  • 如果 productsMap 是跨线程共享的,您可以尝试使用 ConcurrentHashMap,但从 sn-p 来看,它看起来不像是共享的。此外,如果 buildProductMap 是线程安全的,则可以在同步范围之外进行重构。
  • @VikramSingh,很抱歉造成混淆,但如果您注意到它已分配给同名变量 this.productsMap= = productsMap 并且当我提到共享时,我的意思是 this.productsMap
  • 重命名变量名以避免混淆。
  • 这是否可以改变取决于更多的代码。是否有其他方法可以在同一个锁上同步? this.productsMap 是如何使用的?等等。

标签: java concurrency synchronized


【解决方案1】:

由于productsMap 是一个实例级变量,这就是该方法已同步的原因。假设buildProductMap 只是一个实用程序类并且不需要同步,那么您看到productMapBuilder 上的线程被阻塞(而不是死锁)的一个原因可能是products 是一个巨大的列表,它需要时间来处理.当多个线程同时访问这段代码时,对象级锁的争用很高。低争用同步很便宜,但它开始在高争用中产生问题。顺便说一句,您是否分析了线程转储以查看此方法是否确实是真正的原因? productsMap 也是方法级别的变量,所以不需要同步,这只是因为 this.productsMap = productsMap。但是我有一个问题 - 您将 productsMap 分配给实例级变量(因此需要同步)的原因是您将重用它(而不是重新计算)它。这是一次性初始化还是每个用户请求都会发生这种情况?

【讨论】:

  • 不回答问题,包含与“类级变量”(它是一个实例变量)和锁争用无关的内容。
  • “类级别变量”是我已更正的错字 - 我确实在下面提到了“实例级别”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 2011-11-08
相关资源
最近更新 更多