synchronized(this)阻止整个对象?

可能重复:
synchronized block vs synchronized方法?

从接受的答案到这个问题: 在Java关键部分,我应该同步什么? 我明白了

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

和:

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

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

你似乎在混合东西。

首先

 public synchronized void method() { } 

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

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

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

其次,

 synchronized(someObject) { //some instructions } 

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

在你的情况下, someObject碰巧就是this

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

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

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

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

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

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

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

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