有人可以解释“同步”(this)和“同步”(c)之间的区别吗?
我参考了各种答案(1,2,3,4,5),但无法理解和感到困惑。
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");
}
}
}
我能够理解同步的概念,但不能监视对象。请以简单的方式进行解释。
答案 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
块。