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的方法调用指令进行检查。 然而,这种差异在实践中没有多大意义。
他们不做同样的事情。 第一部分从头到尾同步。 第二个是同步块(不是整个方法)。 第二个有一些灵活性。