多个线程能否在 Java 中直接映射的 ByteBuffer 上看到写入?
我正在研究使用从内存映射文件(通过FileChannel.map())构建的ByteBuffers以及内存中直接ByteBuffers的东西。我试图理解并发和内存模型约束。
我已经阅读了所有相关的Javadoc(和源代码),如FileChannel,ByteBuffer,MappedByteBuffer等。很明显,特定的ByteBuffer(和相关子类)有一堆字段,并且从内存模型的角度来看,状态不受保护。因此,如果在跨线程使用特定 ByteBuffer 的状态时,必须进行同步。常见的技巧包括使用ThreadLocal包装ByteBuffer,复制(同步时)以获得指向相同映射字节的新实例等。
给定此方案:
- 管理器具有整个文件的映射字节缓冲区(假设它是<2gb)
B_all
- 管理器在B_all上调用replicate(),position(),limit()和slice()以创建一个新的较小的ByteBuffer,该文件的一个块,并将其提供给线程T1
B_1
- 管理器执行所有相同的操作来创建指向相同映射字节的字节缓冲区,并将其提供给线程 T2
B_2
我的问题是:T1可以同时写入B_1,T2写入B_2并保证看到彼此的变化吗?T3 能否使用B_all来读取这些字节,并保证同时看到 T1 和 T2 的变化?
我知道映射文件中的写入不一定在进程中看到,除非您使用force()指示操作系统将页面写入磁盘。我不在乎这些。对于这个问题,假设此 JVM 是编写单个映射文件的唯一进程。
注意:我不是在寻找猜测(我自己可以很好地做出这些猜测)。我希望引用一些关于内存映射直接缓冲区保证(或不保证)的明确信息。或者,如果您有实际经验或阴性测试用例,那也可以作为充分的证据。
更新:我已经做了一些测试,让多个线程并行写入同一文件,到目前为止,这些写入似乎立即从其他线程中可见。我不确定我是否可以依靠它。