java.nio.ByteBuffer.slice() 线程行为?

标签 java multithreading bytebuffer

我知道 java.nio.ByteBuffer 本身不是线程安全的。但是,如果您通过 slice() 获得共享的派生 ByteBuffer,您是否能够通过不同的切片缓冲区在多个线程中同时访问底层缓冲区的内容?我在 API 规范中找不到任何有关此内容的信息...如果此行为未标准化,您知道它是如何在最常见的虚拟机中实现的吗?

最佳答案

基本上,如果某些东西没有被记录为线程安全的,就假设它不是;如果某些内容被明确记录为是线程安全的,则永远不要假设任何密切相关的内容都是线程安全的,除非另有说明。


正如您所提到的,缓冲区不是线程安全的。 Buffer 记录了这一点:

Buffers are not safe for use by multiple concurrent threads. If a buffer is to be used by more than one thread then access to the buffer should be controlled by appropriate synchronization.

而扩展了BufferByteBuffer的文档与上述并不矛盾。

这是 ByteBuffer#slice() 的文档内容说:

Creates a new byte buffer whose content is a shared subsequence [emphasis added] of this buffer's content.

The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. [emphasis added]

The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer, its mark will be undefined, and its byte order will be BIG_ENDIAN. The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only.

其他类似的方法,例如 #slice(int,int)#alignedSlice(int),记录了类似的行为。

如您所见,缓冲区实例的内容是共享的。该文档没有提到在这种情况下添加线程安全性,因此我们可以自信地假设缓冲区的一般线程安全性适用,即不存在线程安全性。如果写入共享相同内容子序列的任何缓冲区,则所有其他缓冲区都将受到影响。在并发上下文中,如果没有适当的外部同步,这意味着潜在的竞争条件。

我不确定这如何应用于读取和写入不同(即非重叠)子序列。我假设适用于数组的任何行为都适用于这种情况。当然,这没有考虑直接缓冲区。

话虽如此,但还是有一些微妙之处。如文档所述,每个缓冲区都有独立的位置、限制和标记值。这样做的结果是每个缓冲区都可以由单独的线程读取。不过,这是缓冲区和线程之间的一对一映射(除非您添加外部同步)1。这是因为只需读取缓冲区(至少相对读取操作1就是这种情况)和倒回即可修改位置和标记值。


1。我相信多个线程可以在不同步的情况下从同一个缓冲区实例读取,当且仅当它们都使用绝对读取操作并且不使用标记时。换句话说,只要没有线程修改缓冲区的“元状态”。

关于java.nio.ByteBuffer.slice() 线程行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59963919/

相关文章:

java - 如何使用 POI SS 打开 .xlsx 文件?

android - 循环内的 AsyncTask

java - 使用 java.nio.MappedByteBuffer 时防止 OutOfMemory

java - 从 ByteBuffer 中提取 Longs (Java/Scala)

java - 理解 HashMap 中的 `structural modification`

java - 如何在字节缓冲区中表示目标列表

java - ConcurrentHashMap 怎么可能没有 keySet() 方法呢?

java - 如何反转包含 Set<Integer> 的 map ?

java - Guice 字段注入(inject)不起作用(返回 null)

c++ - 并行填充 vector ,顺序不重要