同步对象并更改引用

gme*_*mon 6 java concurrency multithreading synchronized synchronized-block

假设我有一个对象如下:

Map<String, String> m = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

然后我按如下方式同步该对象并更改其引用:

synchronize(m){
    m = new HashMap<>();
}
Run Code Online (Sandbox Code Playgroud)

有了这段代码,m 上的锁会发生什么情况?更新 m 代表的新对象是否仍然安全?或者锁本质上是在旧对象上?

xia*_*.li 6

JLS 17.1开始:

\n\n
\n

同步语句 (\xc2\xa714.19) 计算对对象的引用;\n 然后它尝试在该对象的监视器上执行锁定操作,并且\n 在锁定操作成功之前不会继续执行\n完全的。执行锁定操作后,将执行同步语句的主体。如果主体的执行完成,无论是正常还是突然,都会在同一监视器上自动执行解锁操作。

\n
\n\n

现在问题来了。

\n\n

m 上的锁会发生什么情况?

\n\n

没有什么。这有点令人困惑。实际上,线程在尝试获取锁时持有所引用的对象的锁。 m同步块中的分配m不会自动“切换”执行线程所持有的锁。

\n\n

更新 m 代表的新对象是否仍然安全?

\n\n

这不安全。同一锁上的写入m不同步。

\n\n

或者锁本质上是在旧对象上?

\n\n

是的

\n