【问题标题】:Synchronizing on this and on other object在此对象和其他对象上同步
【发布时间】:2015-08-05 14:19:02
【问题描述】:

我认为这个问题一定是在某个地方问过的,但是当我寻找它时,不幸的是,我只发现了不同的主题。无论如何这里是代码:

public class A {
    Object lockX = new Object();
    Object lockY = new Object();
    Object lockZ = new Object();
    int c1;
    int c2;

    public void foo1() {
        synchronized(lockX) {
            c1++;
        }
    }

    public void bar1() {
        synchronized(lockY) {
            c1++;
        }
    }

    public void foo2() {
        synchronized(lockZ) {
            c2++;
        }
    }

    public void bar2() {
        synchronized(this) {
            c2++;
        }
    }
}

基本上 foo1 和 bar1 是不正确的。它们使用不同的锁来保护 c1,因此实际上 c1 不会受到保护,并且这两个功能可以同时运行。然而,我的问题是关于 foo2 和 bar2。他们还好吗?它们也使用不同的锁,但 bar2 锁定了整个对象,所以它会阻止同时修改 c2 吗?

【问题讨论】:

  • 您有四种不同的锁,lockX,lockY,lockZ 和 this。他们都不会阻止任何其他人。
  • 在一个真实的程序中,如果你只是想从多个线程中计算一些东西,你应该使用 AtomicInteger。

标签: java synchronization


【解决方案1】:

bar2 正在锁定整个对象

一旦你正确理解了互斥锁(mutexes)的语义,你就会意识到这是一句空话。互斥体没有任何固有范围:线程在任何时间点都持有或不持有它。在this 上同步只需获取与this 实例关联的互斥锁。在lockZ上同步会获取一个完全独立的互斥体,并且两者可以同时获取。

【讨论】:

    【解决方案2】:

    foo2 和 bar2 类似于 foo1 和 bar1。在bar2 的情况下,锁位于A 类对象上,而foo2 使用对象lockZ 的锁。

    对象this 不会被锁定,而是对象this 被用作互斥体,并且主体被阻止与synchronized 上this. 上的其他代码部分同时执行

    【讨论】:

      【解决方案3】:

      快速回答是:不。甚至c2 也不受并发访问保护,因为它被不同的对象实例锁定。还有一个更好的形式

          public void bar2() {
              synchronized(this) {
                  c2++;
              }
          }
      

      是

          synchronized public void bar2() {
              c2++;
          }
      

      【讨论】:

        【解决方案4】:

        正如@Marko 中提到的,锁定的语义与您已经设想的不同。

        在对象 X 上同步并不意味着您正在对对象 X 本身应用访问/方法执行限制。当某个线程A 在实例X 上同步时,它会限制其他线程在同一实例X 上同步,直到线程A 在synchronized(X) 块内完成执行,从而释放对象@ 的锁定987654329@。更清楚地说,一次只有一个线程可以获取对象的单个不可变实例上的锁,并且在该锁被释放之前,任何其他试图获取同一实例上的锁的线程都会阻塞。

        将同步块想象成一个有门的房间,这扇门用钥匙打开,当一个线程想要进入房间并在里面做事时,它需要一把钥匙,打开门然后进去,但保持有了它,其他想要使用相同密钥进入房间的线程必须在门上等待,直到里面的线程完成其业务,离开房间并释放密钥以供其他线程使用。如果另一个线程使用不同的密钥,而另一个线程已经在房间里,它可以进入同一个房间并在另一个线程还在里面做它的业务,因此这两个线程可以修改房间里相同的东西,这可能会导致所谓的race condition。

        所以在你的情况下,答案是:否。

        【讨论】:

          猜你喜欢
          • 2016-10-14
          • 1970-01-01
          • 2014-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多