Skip to content
Advertisement

Java mmap MappedByteBuffer

Let’s say I’ve mapped a memory region [0, 1000] and now I have MappedByteBuffer.

Can I read and write to this buffer from multiple threads at the same time without locking, assuming that each thread accesses different part of the buffer for exp. T1 [0, 500), T2 [500, 1000]?

If the above is true, is it possible to determine whether it’s better to create one big buffer for multiple threads, or smaller buffer for each thread?

Advertisement

Answer

Detailed Intro:

If you wanna learn how to answer those questions yourself, check their implementation source codes:

Now it gets a bit more complicated:

When you wanna allocate a MappedByteBuffer, you will get either a

Instead of having to browse internet pages, you could also simply download the source code packages for your Java version and attach them in your IDE so you can see the code in development AND debug modes. A lot easier.

Short (incomplete) answer:

Neither of them does secure against multithreading.

  • So if you ever needed to resize the MappedByteBuffer, you might get stale or even bad (ArrayIndexOutOfBoundsException) access
  • If the size is constant, you can rely on either Implementation to be “thread safe”, as far as your requirements are concerned

On a side note, here also lies an implementation failure creep in the Java implementation:

  • MappedByteBuffer extends ByteBuffer
  • ByteBuffer has the heap byte[] called “hb”
  • DirectByteBuffer extends MappedByteBuffer extends ByteBuffer
  • So DirectByteBuffer still has ByteBuffer’s byte[] hb buffer,
    • but does not use it
    • and instead creates and manages its own Buffer

This design flaw comes from the step-by-step development of those classes (they were no all planned and implemented at the same time), AND the topic of package visibility, resulting in inversion of dependency/hierarchy of the implementation.

Now to the true answer:

If you wanna do proper object-oriented programming, you should NOT share resource unless utterly needed. This ESPECIALLY means that each Thread should have its very own Buffer.

Advantage of having one global buffer: the only “advantage” is to reduce the additional memory consumption for additional object references. But this impact is SO MINIMAL (not even 1:10000 change in your app RAM consumption) that you will NEVER notice it. There’s so many other objects allocated for any number of weird (Java) reasons everywhere that this is the least of your concerns. Plus you would have to introduce additional data (index boundaries) which lessens the ‘advantage’ even more.

The big Advantages of having separate buffers:

  • You will never have to take care of the pointer/index arithmetics
    • especially when it comes to you needing more threads at any given time
  • You can freely allocate new threads at any time without having to rearrange any data or do more pointer arithmetics
  • you can freely reallocate/resize each individual buffer when needed (without worrying about all the other threads’ indexing requirement)
  • Debugging: You can locate problems so much easier that result from “writing out of boundaries”, because if they tried, the bad thread would crash, and not other threads that would have to deal with corrupted data
    • Java ALWAYS checks each array access (on normal heap arrays like byte[]) before it accesses it, exactly to prevent side effects
    • think back: once upon a time there was the big step in operating systems to introduce linear address space so programs would NOT have to care about where in the hardware RAM they’re loaded.
    • Your one-buffer-design would be the exact step backwards.

Conclusion:

If you wanna have a really bad design choice – which WILL make life a lot harder later on – you go with one global Buffer.

If you wanna do it the proper OO way, separate those buffers. No convoluted dependencies and side effect problems.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement