相关疑难解决方法(0)

多线程可以在Java中看到直接映射的ByteBuffer上的写入吗?

我正在研究使用ByteBuffers从内存映射文件(通过FileChannel.map())以及内存中直接ByteBuffers 构建的东西.我试图了解并发和内存模型约束.

我已经阅读了FileChannel,ByteBuffer,MappedByteBuffer等所有相关的Javadoc(和源代码).很明显,特定的ByteBuffer(和相关的子类)有一堆字段,并且状态不受内存模型的保护观点看法.因此,如果跨线程使用该缓冲区,则必须在修改特定ByteBuffer的状态时进行同步.常见的技巧包括使用ThreadLocal包装ByteBuffer,复制(同步)以获取指向相同映射字节的新实例等.

鉴于这种情况:

  1. manager B_all为整个文件提供了一个映射的字节缓冲区(比如它<2gb)
  2. 管理器在B_all上调用duplicate(),position(),limit()和slice()来创建一个新的较小的ByteBuffer B_1,该文件的一大块并将其提供给线程T1
  3. manager执行所有相同的操作来创建B_2指向相同映射字节的ByteBuffer 并将其提供给线程T2

我的问题是:T1可以写入B_1,T2可以同时写入B_2并保证看到彼此的变化吗?T3可以使用B_all来读取这些字节并保证看到T1和T2的变化吗?

我知道,除非您使用force()指示操作系统将页面写入磁盘,否则不一定会在进程中看到映射文件中的写入.我不在乎.假设这个问题,这个JVM是编写单个映射文件的唯一进程.

注意: 我不是在寻找猜测(我可以自己做得很好).我想引用一些关于内存映射直接缓冲区保证(或不保证)的内容.或者,如果您有实际经验或负面测试用例,那么这也可以作为充分的证据.

更新:我已经完成了一些测试,让多个线程并行写入同一个文件,到目前为止,似乎这些写入可以立即从其他线程中看到.我不确定我是否可以依靠它.

java concurrency bytebuffer filechannel memory-mapped-files

24
推荐指数
3
解决办法
7011
查看次数

为什么ByteBuffer的绝对读取不被认为是线程安全的?

我的用例需要直接分配ByteBuffer,写入一次,然后由许多并发线程读取.所有读取都是绝对的,所以我从不关心缓冲区的状态(位置,限制,标记).

关于Keith Gregory的字节缓冲区的这篇文章警告说,即使绝对读取也不被认为是线程安全的:

ByteBufferBufferJavaDoc中介绍了线程安全性; 简短的版本是缓冲区不是线程安全的.显然,在没有竞争条件的情况下,您不能使用来自多个线程的相对定位,但即使绝对定位也无法保证(无论您在查看实现类后如何看待).

(强调我的)

由于这个警告,我在字节缓冲区的每次读取之前调用duplicate.这很容易,但每次读取时额外的对象分配让我很好奇为什么它实际上是必要的.

尽管Keith的向导免责声明,我确实看到了OpenJDK对直接字节缓冲区的绝对读取的实现:

public byte get(int i) {
    return ((unsafe.getByte(ix(checkIndex(i)))));
}
Run Code Online (Sandbox Code Playgroud)

您可以看到它只是委托给Unsafe.getByte(long)"从给定内存地址获取值".

我知道可能存在不同的实现,但对于此操作而言,合理地不能保证线程安全吗?Buffer合同是否只是拒绝保证绝对读取的线程安全性,以避免部分线程安全类的混淆?或者如果警告对于并发写入是合理的,那么我的情况如何,在创建后字节缓冲区未被修改?此外,使用MappedByteBuffer替代品时会有什么变化吗?

有关:

java multithreading nio bytebuffer

7
推荐指数
1
解决办法
1442
查看次数