有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

Keith Gregory在字节缓冲区上的This article警告说,即使是绝对读取也不被认为是线程安全的:

ByteBuffer thread safety is covered in the Buffer 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).

(强调矿山)

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

尽管Keith巧妙地否认了这一点,但我确实看到了OpenJDK的implementation从直接字节缓冲区进行绝对读取:

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

您可以看到它只是委托给^{},它“从给定的内存地址获取一个值”

我知道可能存在不同的实现,但是这个操作有什么不可能是线程安全的呢?Buffer契约是否只是为了避免部分线程安全类的混淆而拒绝保证绝对读取的线程安全?或者,如果警告是针对并发写入的,那么在创建字节缓冲区后未修改字节缓冲区的情况如何?另外,使用^{}时会有什么变化吗

相关的:


共 (1) 个答案

  1. # 1 楼答案

    一方面,缓冲区文档说明应该同步对缓冲区的访问。它并没有说它不能被不同的线程使用。因此,我认为不需要duplicate

    您无法想到某种方法或其他方法的合理非线程安全实现,这是您想象力的一个极限,而不是证明不需要谨慎。特别是考虑到您没有查看Oracle Java代码,当时Oracle声明实现不是线程安全的

    我的建议是:在访问缓冲区时进行一些合理的同步。即使永远不会有一个非线程安全的实现,它也不会花费你很多钱