Atomic reading then writing part of ByteBuffer in Java

I have a ByteBuffer in java and you want to read, then conditionally change this byte, for example. using a method, for example:

public void updateByte(int index) { byte b = this.buffer.getByte(index); if (b == someByteValue) { this.buffer.setByte(index, someNewByte); } } 

How can I make sure that reading and then changing the byte happens atomically?

I don’t want to synchronize the whole ByteBuffer or updateByte , since I want several threads to be able to read / write different bytes of the buffer at the same time (i.e. updateByte can call many threads at the same time, while index is different).

The ByteBuffer I'm using is not supported by byte [], so bb.hasArray() == false in the above example.

+4
java concurrency memory
source share
7 answers

Short answer: you cannot, without resorting to JNI.

Longer answer: There are no atomic updates in the ByteBuffer API. Moreover, the interaction of ByteBuffer with memory is not strictly defined. And in the Sun implementation, the methods used to access raw memory do not try to flush the cache, so you can see outdated results on a multi-core processor.

Also, keep in mind that Buffer (and its subclasses, such as ByteBuffer) are explicitly documented as unsafe threads. If you have multiple threads accessing the same buffer, you (1) rely on implementation behavior for absolute access or (2) write idle code for relative access.

+3
source share

How about providing a set of explicit lock objects for ByteBuffer parts (parts can be very small, for example, in one word, or quite large, for example, four quarter of the buffer)?

When a thread wants to check and change the byte, it must first obtain a lock for the corresponding part, perform its work, and then release the lock.

This will provide access to different parts of the data in multiple streams without global synchronization.

+5
source share

I do not believe that you can access a byte atomically in Java. The best you can do is change the int values. This will allow you to simulate a change in one byte.

You can use Unsafe (on many JVMs) to compare and swap for an array () (heap ByteBuffer) or address () (direct ByteBuffer)

+3
source share

Personally, I would block the mutex until I figure out the offset to write data, and then release the mutex. This way you close very little time

+1
source share

A long long thread about parallel DirectByteBuffer in this list :

The answer should be "YES."

Another example of BIG is NIO. 2. a write / read operation represents byte buffers; this is normal when calling the CompletionHandler.

Due to the fact that in the case of NIO.2 only DirectByteBuffer is used. For a Non-Direct-ByteBuffer that is "cloned" in DirectByteBuffer, these are NOT real-level low-level operations parameters.

+1
source share

It should be possible to block the ByteBuffer. Methods

  • you can create a list of lock objects and lock only one area per read of the byte buffer. As DNA suggests, this should be the quickest solution.
  • or you can even use memory mapping to solve this problem , and then use FileChannel.lock , which also blocks the area of ​​the byte buffer, but at a lower level. Edit : this only protects access from external IMO programs
  • Or you can use some smaller but synchronized ByteBuffers + exchange data. it is interesting to note that threads should see changes immediately from each other (this is where I got the mmap idea)
0
source share

I think creating a critical section of code under lock control should be a clean solution. However, do not use synchronization directly if your use case has a large number of reads compared to writing. I suggest you use ReentrantReadWriteLock as part of your solution. In the function where you modify the ByteBuffer, you take writeLock (). Lock () and then your code. And while reading, use readLock (). Lock (). You can read more about blocking reading and writing at the specified link. In principle, this will allow simultaneous reading, but not simultaneous writing, and when writing, read threads wait

0
source share

All Articles