synchronized(this)阻止整个对象?

时间:2012-08-16 05:36:22

标签: java multithreading

  

可能重复:
  synchronized block vs synchronized method?

从接受的答案回答这个问题:In Java critical sections, what should I synchronize on? 我知道了

public synchronized void foo() {
    // do something thread-safe
}

public void foo() {
    synchronized (this) {
        // do something thread-safe
    }
}

做同样的事情。但是在第一种情况下,我们只对一个对象的方法进行同步,而在第二种情况下,我们使得不可访问的整个对象。那么为什么这两个代码片段会做同样的事情呢?

4 个答案:

答案 0 :(得分:5)

你似乎在混合东西。

首先

public synchronized void method() {
}
从同步的角度来看,

等同于:

public void method() {
    synchronized (this) {
    }
}

已经提到了优点/缺点,各种副本提供了更多信息。

其次,

synchronized(someObject) {
    //some instructions
}

表示同步块中的指令不能由2个线程同时执行,因为它们需要在someObject上获取监视器才能执行此操作。 (这假设someObject是一个不会改变的最终引用。)

在您的情况下,someObject恰好是this

对象中未同步的任何代码仍然可以同时执行,即使this上的监视器由一个线程持有,因为它正在运行synchronized块。换句话说,synchronized(this)不会“锁定整个对象”。它只能防止2个线程同时执行同步块。

最后,如果你有两个synchronized方法(都使用this作为锁),如果一个线程(T1)获取this上的锁来执行这两个方法之一,不允许其他线程执行这两种方法中的任何,因为它们需要获取this上已锁定的锁。

这种情况可能会在关键部分产生争用,在这种情况下,必须使用更精细的锁定策略(例如,使用多个锁)。

答案 1 :(得分:1)

我们不同步对象,而是同步一段代码。在第一个代码块是方法本身,而在第二个代码块是synchronized块。

该对象仅提供锁定,以防止多个线程同时进入该代码块。在第一种情况下,this对象(调用该方法的对象)将隐式用作锁,而在第二种情况下,它不一定必须是this对象,它也可能是其他一些对象。

答案 2 :(得分:1)

他们做同样的事情。第一种形式是第二种形式的简写。

这两个结构之间的一个细微差别是 - 同步块被编译为monitorenter(操作码0xC2)和monitorexit(操作码0xC3)指令。 编译时,synchronized方法在运行时常量池中区分 ACC_SYNCHRONIZED标志,由JVM检查方法调用指令。然而,这种差异在实践中没有多大意义。

答案 3 :(得分:0)

他们不做同样的事情。第一部分从头到尾同步。第二个是同步块(不是整个方法)。第二个有一些灵活性。