My use case requires a directly allocated ByteBuffer
that is written to once and thereafter read by many concurrent threads. 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:
ByteBuffer
thread safety is covered in theBuffer
JavaDoc; 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
. 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:
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".
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? 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?
Related: