繁体   English   中英

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

[英]Why are absolute reads from a ByteBuffer not considered thread-safe?

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

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

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

(强调我的)

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

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

public byte get(int i) {
    return ((unsafe.getByte(ix(checkIndex(i)))));
}

您可以看到它只是委托给Unsafe.getByte(long) ,它“从给定的内存地址中获取值”。

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

有关:

其中一个Buffer文档指出应该同步对缓冲区的访问。 它没有说它不能被不同的线程使用。 所以我认为不需要duplicate

你不能想到某种方法或其他方法的合理的非线程安全实现更多是你的想象力的限制,而不是证明没有必要谨慎。 特别是考虑到你没有查看Oracle Java代码,当时Oracle声称实现不是线程安全的。

我建议:访问缓冲区时要做一些合理的同步。 即使永远不会有非线程安全实现,也不会花费太多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM