同步此对象和其他对象

时间:2015-08-05 14:19:03

标签: java synchronization

我认为这个问题肯定是在某个地方被问过的,但是当我找到它时,我很遗憾只能找到不同的主题。无论如何这里是代码:

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的修改?

4 个答案:

答案 0 :(得分:5)

  

bar2正在锁定整个对象

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

答案 1 :(得分:1)

foo2bar2foo1bar1类似。如果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上进行同步,直到线程Asynchronized(X)内完成执行阻止并因此释放对象X上的锁定。为了更清楚,一次只有一个线程可以获取对象的单个不可变实例的锁,并且在释放此锁之前,试图获取同一实例上的锁的任何其他线程都将阻塞。 / p>

将同步块看作一个带门的房间,这扇门打开时带钥匙,当一个线程要进入房间并在里面做东西时,它需要一把钥匙,打开门然后进去但保持关键是,其他想要用相同的密钥进入房间的线程必须在门上等待,直到线程内部完成其业务,离开房间并设置密钥可供其他线程使用。如果另一个线程使用了另一个线程,而另一个线程已经在房间内,它可以进入同一个房间并在其他线程仍然在那里进行业务,因此这两个线程可以修改房间中的相同内容,这可能会导致所谓的race condition

因此,在您的情况下,答案是:否。

相关问题