简体   繁体   English

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

[英]java.nio.ByteBuffer.slice() Threading Behaviour?

I understand that java.nio.ByteBuffer itself is not thread safe.我知道 java.nio.ByteBuffer 本身不是线程安全的。 However, if you obtain a shared, derived ByteBuffer via slice(), will you be able to access the contents of the underlying buffer concurrently in multiple threads, through different slice'd buffers?但是,如果您通过 slice() 获得共享的派生 ByteBuffer,您是否能够通过不同的切片缓冲区在多个线程中同时访问底层缓冲区的内容? I cannot find anything about this in the API spec... If this behaviour isn't standardised, do you know how it's implemented in the most common VMs?我在 API 规范中找不到任何关于此的内容...如果此行为未标准化,您知道它是如何在最常见的 VM 中实现的吗?

Basically, if something isn't documented to be thread-safe, assume it's not;基本上,如果某些东西没有被记录为线程安全的,就假设它不是; if something is explicitly documented as not being thread-safe, never assume anything closely related is thread-safe unless documented otherwise.如果某些东西被明确记录为不是线程安全的,除非另有说明,否则永远不要假设任何密切相关的东西都是线程安全的。


As you mention, buffers are not thread-safe.正如您所提到的,缓冲区不是线程安全的。 This is documented by Buffer :这是由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.如果一个缓冲区被多个线程使用,那么对缓冲区的访问应该由适当的同步控制。

And the documentation of ByteBuffer , which extends Buffer , does not contradict the above.扩展BufferByteBuffer文档与上述内容并不矛盾。

Here's what the documentation of ByteBuffer#slice() says:这是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 .新缓冲区的位置将为零,其容量和限制将是该缓冲区中剩余的字节数,其标记未定义,其字节顺序为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.当且仅当此缓冲区为直接缓冲区时,新缓冲区为直接缓冲区,且仅当此缓冲区为只读时,新缓冲区为只读缓冲区。

Other similar methods, such as #slice(int,int) and #alignedSlice(int) , document similar behavior.其他类似的方法,例如#slice(int,int)#alignedSlice(int) ,记录了类似的行为。

As you can see, the contents of the buffer instances is shared.如您所见,缓冲区实例的内容是共享的。 The documentation does not mention anything about adding thread-safety in this situation, thus we can confidently assume the general thread-safety of buffers applies—that is, there is no thread-safety.文档没有提到在这种情况下添加线程安全的任何内容,因此我们可以自信地假设缓冲区的一般线程安全是适用的——也就是说,没有线程安全。 If any buffer sharing the same subsequence of contents is written to, all the other buffers will be affected.如果写入共享相同内容子序列的任何缓冲区,则所有其他缓冲区都将受到影响。 In a concurrent context, without proper external synchronization, this means potential race-conditions.在并发上下文中,如果没有适当的外部同步,这意味着潜在的竞争条件。

I'm not positive how this applies to reading from and writing to distinct (ie non-overlapping) subsequences.我不肯定这如何适用于读取和写入不同的(即非重叠)子序列。 I assume whatever behavior applies to arrays applies in this case.我假设在这种情况下适用于数组的任何行为都适用。 Of course, that doesn't take into account direct buffers.当然,这并没有考虑直接缓冲区。

That all being said, there are some subtleties to this.话虽如此,这其中有一些微妙之处。 As documented, each buffer will have independent position, limit, and mark values.如文档所述,每个缓冲区将具有独立的位置、限制和标记值。 A consequence of this is that each buffer can be read by a separate thread.这样做的结果是每个缓冲区都可以由单独的线程读取 However, this is a one-to-one mapping between buffer and thread (unless you add external synchronization) 1 .但是,这是缓冲区和线程之间的一对一映射(除非您添加外部同步) 1 This is because the position and mark values can be modified just by reading a buffer (at least, that's the case with relative read operations 1 ) and rewinding.这是因为位置和标记值可以通过读取缓冲区(至少,相对读取操作1 的情况)和回绕来修改。


1. I believe multiple threads could read from the same buffer instance without synchronization if, and only if, they all use the absolute read operations and don't use marks. 1. 我相信多个线程可以在不同步的情况下从同一个缓冲区实例中读取,当且仅当它们都使用绝对读取操作并且不使用标记时。 In other words, as long as none of the threads modify the "meta-state" of the buffer.换句话说,只要没有一个线程修改缓冲区的“元状态”。

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

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