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

ReentrantReadWriteLock与Java内存模型交互及线程同步调试疑惑

ReentrantReadWriteLock写锁同步后的内存可见性问题

写锁的内存语义(基于Java内存模型)

ReentrantReadWriteLock的写锁完全遵循Java内存模型的同步规则:

  • 写锁释放操作:会将当前线程本地缓存的所有共享变量修改刷新到主内存,同时释放锁资源
  • 写锁获取操作:会使当前线程的本地缓存失效,后续读取共享变量必须从主内存重新加载
  • 从happens-before规则来看:线程A释放写锁的动作,happens-before线程B获取同一个写锁的动作。这意味着线程A在释放锁前的所有共享变量修改,线程B在获取锁后的所有操作都应该能看到。

针对你的场景分析

按你给出的事件顺序:

  1. 线程A的写锁释放已经把long变量的新值同步到主内存
  2. 线程B在步骤4获取写锁时,会触发本地缓存失效,此时它的内存视图已经和主内存同步——也就是说,线程B在获取写锁之后,任何对该long变量的读取都应该拿到新值
  3. 你观察到线程B在步骤6(释放锁后)读到旧值,这不符合JMM的规范,大概率是以下原因之一:
    • 事件顺序确认有误:线程B的读取操作可能实际发生在释放锁之前,甚至是获取锁之前(比如代码逻辑的分支、异步操作导致顺序混乱)
    • 锁实例不唯一:线程A和线程B使用的不是同一个ReentrantReadWriteLock实例,导致写锁的同步屏障完全不起作用
    • JIT重排序优化:极端情况下,JIT编译器可能对线程B的读取操作做了重排序,跳过了内存同步步骤(可以通过添加volatile修饰变量,或者在读取前插入内存屏障Unsafe.loadFence()来验证)

排查建议

  • 先确认线程A和线程B使用的是同一个ReentrantReadWriteLock对象,这是同步生效的前提
  • 在线程B获取写锁后立即读取变量并打印,对比释放锁后的读取结果,判断同步是否在获取锁时就已生效
  • 临时将long变量改为volatile类型,如果现象消失,说明原问题确实是内存可见性导致的,进一步排查锁的使用逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:43:18