线程缓存会同步到主内存

线程缓存会同步到主内存

什么时候从“线程缓存 ->主内存 ”?

  1. 退出 synchronized 同步块(解锁 unlock)

    这是你项目中 PersistTask.add() 方法用到的机制。
    规则: 当线程退出一个 synchronized 块时,它必须将该线程工作内存中所有共享变量的最新值刷新回主内存。
    目的: 确保下一个拿到锁的线程能看到最新的修改。

  2. 对 volatile 变量执行写操作
    规则: 当线程对一个 volatile 修饰的变量进行赋值时,JVM 会立即将这个新值刷新到主内存。
    特点: 即使没有加锁,其他线程也能立刻看到这个变量的变化。

  3. 线程结束(Thread Termination)
    规则: 当一个线程执行完毕(run 方法结束)并死亡时,它会将所有共享变量的值同步回主内存。
    场景: 比如你在子线程里算完一个结果,主线程通过 thread.join() 等待子线程结束后,就能拿到最新的结果。

  4. 调用特定的原子类或并发工具方法
    Java 的 java.util.concurrent 包里的很多工具内部都使用了 volatile 或 CAS 操作,它们也会触发同步:
    原子类: 如 AtomicInteger.incrementAndGet()。
    线程安全容器: 如 ConcurrentHashMap.put()、BlockingQueue.put()。
    原理: 这些方法的底层实现通常涉及 volatile 写或 Unsafe 操作,从而保证可见性。

  5. 显式使用 Unsafe 或 VarHandle
    如果你直接使用底层的 Unsafe.storeFence() 等方法,可以强制刷新缓存。但这属于高级用法,普通业务代码很少见。

反向操作:什么时候从“主内存 -> 线程缓存”?

为了保证你能读到别人改过的数据,以下情况会触发读取主内存:

  • 进入 synchronized 同步块(加锁 lock)。
  • 读取 volatile 变量。
  • 线程启动(Thread.start):子线程刚开始运行时,会从主内存拷贝一份父线程修改过的数据。
  • 调用 thread.join() 返回后。

总结一张表

动作 方向 触发条件
刷新 (Flush) 工作内存 -> 主内存 1. 解锁 (synchronized 结束)
2. 写 volatile 变量
3. 线程结束
读取 (Load) 主内存 -> 工作内存 1. 加锁 (synchronized 开始)
2. 读 volatile 变量
3. 线程启动
posted @ 2026-04-27 13:21  deyang  阅读(4)  评论(0)    收藏  举报