Java:如果同步发生更改,它不会阻塞

Java:如果同步发生更改,它不会阻塞,java,multithreading,Java,Multithreading,相关的 输出: from first block start 0 from second block start from second block done 1 1 from first block done 在相关答案中,它们都保持原始参考,因此第二个块应被阻止,直到第一个块完成 然而,第二个块确实进行了一次a.lockObj更改了第一个块。为什么?您正在创建两个对象,因此让我们命名它们以供参考: 在字段初始值设定项中创建ObjA 在sleep(1000) 线程中的synchroniz

相关的

输出:

from first block start
0
from second block start
from second block done
1
1
from first block done
在相关答案中,它们都保持原始参考,因此第二个块应被阻止,直到第一个块完成


然而,第二个块确实进行了一次
a.lockObj
更改了第一个块。为什么?

您正在创建两个对象,因此让我们命名它们以供参考:

  • 在字段初始值设定项中创建ObjA

  • 在sleep(1000)

线程中的
synchronized(a.lockObj)
块锁定在ObjA上

由于启动线程后您有
sleep(100)
,因此当主线程到达其
synchronized(a.lockObj)
块时,线程将更改
a.lockObj
以引用ObjB,从而将锁定到不同的对象上

作为不同的对象,代码不会阻塞


提示:锁位于对象上,而不是引用变量。

您正在创建两个对象,因此让我们将它们命名为引用:

  • 在字段初始值设定项中创建ObjA

  • 在sleep(1000)

线程中的
synchronized(a.lockObj)
块锁定在ObjA上

由于启动线程后您有
sleep(100)
,因此当主线程到达其
synchronized(a.lockObj)
块时,线程将更改
a.lockObj
以引用ObjB,从而将锁定到不同的对象上

作为不同的对象,代码不会阻塞


提示:锁位于对象上,而不是引用变量。

您的两个线程使用不同的锁。第一个线程保存a.lockObj引用的第一个对象实例,第二个线程保存a.lockObj引用的第二个对象实例。这是很容易避免的:不要重新分配正在同步的对象。另一个答案中的一些措辞让我感到困惑,特别是“reference”一词的使用,让我们称该成员为a.lockObja reference;
a.lockObj
引用的
对象是引用对象。同步取决于引用的对象,而不是引用。有两个不同的引用对象用于同步;结果很糟糕。您的两个线程使用了不同的锁。第一个线程保存a.lockObj引用的第一个对象实例,第二个线程保存a.lockObj引用的第二个对象实例。这是很容易避免的:不要重新分配正在同步的对象。另一个答案中的一些措辞让我感到困惑,特别是“reference”一词的使用,让我们称该成员为a.lockObj
a reference;
a.lockObj
引用的
对象是引用对象。同步取决于引用的对象,而不是引用。有两个不同的引用对象用于同步;结果是悲惨的。
from first block start
0
from second block start
from second block done
1
1
from first block done