【问题标题】:Using synchronized blocks for different methods in the same class对同一类中的不同方法使用同步块
【发布时间】:2016-09-21 20:35:59
【问题描述】:

我正在阅读来自oracle 的多线程官方教程,我遇到了这个例子(假设c1c2 从未一起使用):

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
      }
    }
}

据说通过使用lock 1 & lock 2,相比在同步块中使用this这个词,它有助于减少不必要的阻塞。

但是,我真的不明白这如何有助于减少阻塞,因为它们彼此不依赖。我有多个线程,每个线程同时运行这两种方法,当我使用锁定对象和 this 关键字时,性能相当相似。

有人可以在这里帮助解释我的困惑吗?喜欢看一个例子的解释,以清楚地说明差异。


除了这里的讨论之外,post 也有助于澄清我的疑问。关键点:在方法上设置同步意味着线程必须在进入该方法之前获取对象实例上的锁

【问题讨论】:

  • 要查看这种情况下的性能差异,您必须使用大量线程随机并发地调用您的 2 个方法进行大量调用。但是,如果调用不仅仅是增加一个变量,那么 1 与 2 锁之间的差异会更加明显。

标签: java multithreading performance synchronization


【解决方案1】:

您正在使用两种不同的锁 - 一种用于保护 inc1,另一种用于保护 inc2。这意味着线程 X 可以运行 inc1 而另一个线程正在运行 inc2。如果他们使用相同的锁(无论是this 还是不同的锁对象),您将无法同时运行它们。因此,至少在理论上,拥有两个不同的锁应该会提高您在这种情况下的性能。

【讨论】:

  • 我明白你的意思。我想我的困惑是,如果在这种情况下分别通过两种方法更新 c1 和 c2,与只使用一个锁相比,拥有两个不同的锁会影响性能。从您的回答中,我认为您是说使用相同锁的同步块不会同时运行 - 在这种情况下,如果 c1 在不同的线程上更新,c2 将不会更新?
  • @hao 正是——这就是我们有锁的原因——以防止一个线程干扰另一个线程,无论它们是否运行相同的方法。
  • 重点是,由于您试图保护两个自变量,您可以使用两个独立的锁。如果线程 A 正在调用 inc1(),这不一定是阻止线程 B 进入 inc2() 的理由。
  • 谢谢,同一个锁的同步块,当其中一个块被一个线程访问时,将全部被锁定。这是正确的理解方式吗?
  • @hao yup,没错。
猜你喜欢
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2011-11-28
  • 2012-09-14
相关资源
最近更新 更多