在此对象和其他对象上同步

Synchronizing on this and on other object

我想这个问题一定有人问过,但不幸的是,当我寻找它时,我只找到了不同的主题。无论如何,这是代码:

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 吗?

bar2 is locking whole object

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

foo2bar2类似于foo1bar1。在 bar2 的情况下,锁在 class A 对象上,而 foo2 正在使用对象 lockZ.

的锁

对象 this 没有被锁定,而是对象 this 被用作互斥锁,主体被阻止与其他代码段同时执行 synchronized this.

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

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

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

如@Marko 所述,锁定的语义与您已经设想的不同。

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

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

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