我认为这个问题肯定是在某个地方被问过的,但是当我找到它时,我很遗憾只能找到不同的主题。无论如何这里是代码:
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的修改?
答案 0 :(得分:5)
bar2正在锁定整个对象
一旦正确理解了互斥锁(互斥锁)的语义,您就会意识到这是一个空语句。互斥锁没有任何固有的范围:线程在任何时间点都会保留或不保留它。在this
上进行同步只会获取与this
实例关联的互斥锁。在lockZ
上同步获取完全独立的互斥锁,并且两者都可以同时获取。
答案 1 :(得分:1)
foo2
和bar2
与foo1
和bar1
类似。如果bar2
,则锁定在类A
对象上,而foo2
正在使用对象锁lockZ
。
对象this
未被锁定,而对象this
被用作互斥锁,并且阻止正文与其他代码段同时执行synchronized
this.
1}}
答案 2 :(得分:1)
快速回答是:不。甚至c2
也不受并发访问保护,因为它被不同的对象实例锁定。
public void bar2() {
synchronized(this) {
c2++;
}
}
是
synchronized public void bar2() {
c2++;
}
答案 3 :(得分:0)
正如@ Marko所提到的,锁定的语义与你已经设想的不同。
在对象X
上进行同步并不意味着您正在对对象X
本身应用访问/方法执行限制。当某个线程A
在实例X
上同步时,它会限制其他线程在同一个实例X
上进行同步,直到线程A
在synchronized(X)
内完成执行阻止并因此释放对象X
上的锁定。为了更清楚,一次只有一个线程可以获取对象的单个不可变实例的锁,并且在释放此锁之前,试图获取同一实例上的锁的任何其他线程都将阻塞。 / p>
将同步块看作一个带门的房间,这扇门打开时带钥匙,当一个线程要进入房间并在里面做东西时,它需要一把钥匙,打开门然后进去但保持关键是,其他想要用相同的密钥进入房间的线程必须在门上等待,直到线程内部完成其业务,离开房间并设置密钥可供其他线程使用。如果另一个线程使用了另一个线程,而另一个线程已经在房间内,它可以进入同一个房间并在其他线程仍然在那里进行业务,因此这两个线程可以修改房间中的相同内容,这可能会导致所谓的race condition。
因此,在您的情况下,答案是:否。