同步中不同监视对象的目的

时间:2018-11-06 09:38:15

标签: java

有人可以解释“同步”(this)和“同步”(c)之间的区别吗?

我参考了各种答案(12345),但无法理解和感到困惑。

public class Check {

    Consumer c = new Consumer(null);

    public void getSynch() {

        synchronized (this) {
            // doing some task
            System.out.println("Start");
        }

        synchronized (c) {
            // doing some task
            System.out.println("End");
        }

    }

}

我能够理解同步的概念,但不能监视对象。请以简单的方式进行解释。

1 个答案:

答案 0 :(得分:1)

synchronized始终在监视器对象上工作(有时也称为锁或信号灯)。将其视为令牌:当线程进入同步块时,它将对令牌进行分级,而其他线程则需要等待令牌返回。如果您有多个不同的监视器对象,则您基本上具有不同的令牌,因此在不同监视器上运行的同步块可以并行运行。

有很多可能性,还有很多用例。一个可能是一个类的多个实例可以并行运行,但需要访问共享的非线程安全资源。然后,您可以使用该资源或代表该资源“令牌”的任何其他对象作为监视对象。

但是,请注意,可能会出现死锁,例如在以下情况下:

第1块:

synchronized(A) {
  //do something with A
  synchronized(B) {
    //do something with B
  }
}

第2块:

synchronized(B) {
  //do something with B
  synchronized(A) {
    //do something with A
  }
}

这里两个外部同步块可以并行输入,因为两个监视器A和B可用,但随后需要抓住另一个监视器,并且由于它们现在已锁定,因此两个线程都必须等待-类死锁。

还可以查看同样处理该主题的dining philosophers problem(在这里,叉子可以视为监视对象)。

编辑:

对于您的情况(已发布的代码),多个线程可以尝试在getSynch()的同一实例上调用Check。第一个块在实例本身上进行同步,从而防止多个线程在同一实例上被调用时进入该块。

第二个块在c上同步,synchronized(this) { ... }是一个不同的对象,并且可能随时间变化。假设第一个块(c)更改了Consumer以引用synchronized(c)的另一个实例。在这种情况下,您可能有多个线程并行运行该块,例如如果一个线程在另一线程重新分配c之前进入了for块。