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