0

可能重复:
同步块与同步方法?

从这个问题的公认答案:在 Java 关键部分中,我应该同步什么? 我学到了

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

和:

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

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

4

4 回答 4

6

你似乎在混合东西。

首先

public synchronized void method() {
}

从同步的角度来看,等效于:

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

已经提到了优点/缺点,并且各种重复提供了更多信息。

第二,

synchronized(someObject) {
    //some instructions
}

means that the instructions in the synchronized block can't be executed simultaneously by 2 threads because they need to acquire the monitor on someObject to do so. (That assumes that someObject is a final reference that does not change).

In your case, someObject happens to be this.

Any code in your object that is not synchronized, can still be executed concurrently, even if the monitor on this is held by a thread because it is running the synchronized block. In other words, synchronized(this) does NOT "lock the whole object". It only prevents 2 threads from executing the synchronized block at the same time.

Finally, if you have two synchronized methods (both using this as a lock), if one thread (T1) acquires a lock on this to execute one of those 2 methods, no other thread is allowed to execute any of the two methods, because they would need to acquire the lock on this, which is already held by T1.

That situation can create contention in critical sections, in which case a more fine grained locking strategy must be used (for example, using multiple locks).

于 2012-08-16T11:24:43.957 回答
1

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

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

于 2012-08-16T05:58:17.587 回答
1

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

这两种结构之间的一个小区别是 - 同步块被编译成monitorenter(op-code 0xC2) 和monitorexit(op-code 0xC3) 指令。编译时,同步方法在运行时常量池中通过ACC_SYNCHRONIZED标志来区分,该标志由 JVM 的方法调用指令检查。但是,这种差异在实践中并没有太大意义。

于 2012-08-16T06:11:54.227 回答
0

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

于 2012-08-16T05:45:05.477 回答