You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用锁能否替代volatile解决问题?Java线程安全测试存疑

问题1:使用锁能否缓解volatile关键字所处理的问题?

可以,而且锁的能力覆盖了volatile的作用范围,甚至能解决更多问题:

  • volatile的核心作用是保证变量的可见性和禁止指令重排序,但无法保证复合操作的原子性(比如i++这类读-改-写操作)。
  • 以synchronized为例,它的内存语义是:进入同步块时,会将线程工作内存中的变量刷新为主内存的最新值;退出同步块时,会将工作内存中修改后的变量写回主内存。同时,synchronized还能保证同步块内代码的原子性。
  • 所以锁不仅能解决volatile处理的可见性、指令重排序问题,还能处理volatile搞不定的原子性场景,完全可以替代volatile解决它对应的问题。

问题2:为何未复现预期的线程安全问题?

这是预期结果,不是巧合,核心原因是你用了synchronized锁,它的内存语义已经替代了volatile的可见性保障:

  1. happens-before规则:同一个锁的解锁操作,happens-before后续对该锁的加锁操作。也就是说,update方法退出同步块(解锁)时,currMap的新值已经被写回主内存;read方法进入同步块(加锁)时,会从主内存读取currMap的最新值,不会读到旧缓存。
  2. 结合你的代码分析:
    • update里的currMap = newMap操作在同步块内,退出时会强制刷新到主内存;
    • read方法在同步块内读取currMap,必然会拿到主内存的最新引用,而不是线程本地缓存的旧引用;
    • 哪怕currMap没加volatile,锁的内存屏障已经保证了变量的可见性,所以read永远不会读到被移除了key=0的旧map,自然不会返回-1,你的断言assertTrue(readWrong.get() > 0)会一直失败。

内容的提问来源于stack exchange,提问作者petabyte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:37:22