Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Options to make Java's ByteBuffer thread safe

What options do I have to make a ByteBuffer thread safe? It is known that it is not thread safe as it safes position, limit and some(/all?) methods depend on this internal state.

For my purposes it will be sufficient if multiple read-threads are safe, but for other future visitors I would like to know what technics/tricks/traps I need to know to make it completely thread safe.

What I have in mind:

  • Synchronizing or using ReadWrite locks for all methods. Probably the slowest approach (?)
  • Subclassing ByteBuffer and avoid persisting thread-bound state like position etc. And throwing exceptions accordingly for all methods which need to use internal state. This would be the fastes. But are there any traps? (except that I'll have to read the directly mapped memory into heap memory ...)

What other tricks could I use? How would I e.g. implement a "clone bytes on read" with DirectBuffer - is it possible at all? Would probably slicing the full ByteBuffer (ByteBuffer.slice) be involved in one solution?

Update: What is meant in this question with "duplicate (while synchronized) to get a new instance pointing to the same mapped bytes"

like image 784
Karussell Avatar asked Jun 22 '12 09:06

Karussell


People also ask

Are Bytebuffer thread safe?

Note that ByteBuffers are not safe for use by multiple concurrent threads. When a read or write operation is initiated then care must be taken to ensure that the buffer is not accessed until the operation completes.

What are thread safe methods?

A data type or static method is threadsafe if it behaves correctly when used from multiple threads, regardless of how those threads are executed, and without demanding additional coordination from the calling code.

How do I know if a method is thread safe?

To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.


1 Answers

A Buffer class could be made thread-safe ... in the sense that the individual operations were properly synchronized, etcetera. However, the API is not designed with multiple threads in mind, so this this is probably a waste of time.

The basic problem is that the individual operations on a Buffer are too fine-grained to be the unit of synchronization. An application cannot meaningfully synchronize at the level of the get and put operations, or flip, position and so on. Generally speaking, an application needs to perform sequences of these operations atomically in order to synchronize effectively.

The second problem is that if you do synchronize at a fine level, this is likely to add significant overheads on the method calls. Since the point of using the Buffer APIs is to do I/O efficiently, this defeats the purpose.


If you do need to synchronize thread access to a shared buffer, it is better to use external synchronization; e.g. something like this:

    synchronized (someLock) {
        buffer.getByte();
        buffer.getLong();
        ...
    }

Provided all threads that use a given buffer synchronize properly (e.g. using the same lock object), it doesn't matter that the Buffer is not thread-safe. Thread safety is managed externally to the buffer object, and in a more coarse-grained fashion.


As comments point out, you could also use ByteBuffer.slice() or buffer.asReadOnlyBuffer() to give you another buffer with the existing one as backing. However, the javadocs do not guarantee thread-safety in either case. Indeed, the javadocs for Buffer make this blanket statement:

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.

like image 141
Stephen C Avatar answered Sep 20 '22 05:09

Stephen C