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

单JVM中用synchronized保证两个MappedByteBuffer的putLong原子性可行吗?

问题解答

不能保证。原因如下:

  • MappedByteBuffer的写入本质:putLong只是把数据写入JVM管理的内存映射区域(属于操作系统的页缓存),并不会立刻同步到磁盘。操作系统会根据自身的页置换策略异步刷盘——可能先刷buffer1对应的页,还没刷buffer2时,若JVM崩溃或OS异常,读应用就会看到buffer1的变更,buffer2还是旧值,直接破坏事务性要求。

  • synchronized和force()的局限性:你用synchronized只能保证单JVM内两个putLong的执行不会被打断,确保内存里的两个更新是顺序完成的,但管不了操作系统的刷盘顺序。就算你在同步块末尾调用buffer1.force()和buffer2.force()强制刷盘,这两个force()是独立操作,OS没有跨多个文件的原子刷盘机制——先刷完buffer1后如果出问题,buffer2的更新还是不会落地。

要实现跨JVM的事务性(要么全看到,要么全看不到),可以试试这些方案:

  • 事务标记文件方案:

    1. 先写入buffer1和buffer2的新数据
    2. 写入一个单独的标记文件(比如写入固定的完成标识,或者更新标记文件的版本号)
    3. 读应用先检查标记文件:只有标记有效(比如版本号更新完成),才读取两个数据文件的新值;否则读取旧值。如果写入过程中崩溃,标记文件没写完,读应用就不会感知到任何变更。
  • 原子文件重命名方案:

    1. 把新数据写入两个临时文件(比如file1.tmp、file2.tmp)
    2. 写完后,分别将临时文件原子重命名为正式文件(比如file1.dat、file2.dat)。注意:同一个文件系统下,操作系统的文件重命名操作是原子性的
    3. 读应用只读取正式文件,这样要么看到全部新文件,要么还是旧文件,不会出现部分更新的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:27:21