简体   繁体   English

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

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

My use case requires a directly allocated ByteBuffer that is written to once and thereafter read by many concurrent threads. 我的用例需要一个直接分配的ByteBuffer ,它被写入一次,然后由许多并发线程读取。 All reads are absolute and so I'm never concerned with the buffer's state (position, limit, mark). 所有读取都是绝对的,所以我从不关心缓冲区的状态(位置,限制,标记)。

This article on byte buffers by Keith Gregory warns that even absolute reads are not considered thread-safe: 关于Keith Gregory的字节缓冲区的这篇文章警告说,即使绝对读取也不被认为是线程安全的:

ByteBuffer thread safety is covered in the Buffer JavaDoc; Buffer JavaDoc中介绍了ByteBuffer线程安全性; the short version is that buffers are not thread-safe. 简短的版本是缓冲区不是线程安全的。 Clearly, you can't use relative positioning from multiple threads without a race condition, but even absolute positioning is not guaranteed (regardless of what you might think after looking at the implementation classes) . 显然,在没有竞争条件的情况下,您不能使用来自多个线程的相对定位, 但即使绝对定位也无法保证(无论您在查看实现类后如何看待)

(emphasis mine) (强调我的)

Because of this warning, I'm preceding every read from the byte buffer with a call to duplicate . 由于这个警告,我在字节缓冲区的每次读取之前调用duplicate This is easy enough, but the extra object allocation on every single read has me curious why it's actually necessary. 这很容易,但每次读取时额外的对象分配让我很好奇为什么它实际上是必要的。

Despite Keith's wizardly disclaimer, I did look at OpenJDK's implementation of an absolute read from a direct byte buffer: 尽管Keith的向导免责声明,我确实看到了OpenJDK对直接字节缓冲区的绝对读取的实现

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

You can see that it simply delegates to Unsafe.getByte(long) , which "fetches a value from a given memory address". 您可以看到它只是委托给Unsafe.getByte(long) ,它“从给定的内存地址中获取值”。

I understand that different implementations could exist, but what reasonably couldn't be thread-safe about this operation? 我知道可能存在不同的实现,但是对于此操作而言,合理地不能保证线程安全吗? Does the Buffer contract simply decline to guarantee thread-safety for absolute reads in order to avoid the confusion of a partially thread-safe class? Buffer契约是否只是拒绝保证绝对读取的线程安全性,以避免部分线程安全类的混淆? Or if the warning is justified for concurrent writes, what about my situation, in which the byte buffer is unmodified after creation? 或者如果警告对于并发写入是合理的,那么我的情况如何,在创建后字节缓冲区未被修改? Also, would anything change when using a MappedByteBuffer instead? 而且,使用MappedByteBuffer时会有什么变化吗?

Related: 有关:

For one the Buffer documentation states that access to the buffer should be synchronized. 其中一个Buffer文档指出应该同步对缓冲区的访问。 It does no say that it must not be used by different threads. 它没有说它不能被不同的线程使用。 So I think a duplicate is not required. 所以我认为不需要duplicate

That you can not think of a reasonable non-threadsafe implementation of some method or other is more a limit of your imagination than proof that caution is not necessary. 你不能想到某种方法或其他方法的合理的非线程安全实现更多是你的想象力的限制,而不是证明没有必要谨慎。 Especially considering that you did not look at the Oracle Java code, when it was Oracle stating that the implementation is not threadsafe. 特别是考虑到你没有查看Oracle Java代码,当时Oracle声称实现不是线程安全的。

My advise: do some reasonable synchronization when accessing the buffer. 我建议:访问缓冲区时要做一些合理的同步。 Even if there never will be a non-threadsafe implementation it will not cost you much. 即使永远不会有非线程安全实现,也不会花费太多。

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

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