Java Memory Mapping Read / Write Multithreading Files

I have 2 threads accessing the same large file (.txt) at the same time.

The first thread is read from the file. The second stream writes to a file.

Both threads access the same block, for example. (start: 0, blockize: 10), but with different channels and buffer instances

Reader:

{
     int BLOCK_SIZE = 10;
     byte[] bytesArr = new byte[BLOCK_SIZE];
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "r");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, BLOCK_SIZE);
     map.get(bytesArr , 0, BLOCK_SIZE);
     channel.close();
}

      

Writer:

{
     int BLOCK_SIZE = 10;
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
     map.put(bytesToWrite);
     channel.close();
}

      

I know that if both run at the same time, I will get Overlapping Exceptions! BUT, what I would like to know is at what point exactly the weave occurs? I mean when does "blocking" occur exactly? Example: Allow the author to access first, and then, if the reader tries to access, at what point is possible:

 FileChannel channel = randomFile.getChannel();
 // 1- can reader access here?
 MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
 // 2- can reader access here?
 map.put(bytesToWrite);
 // 3- can reader access here?
 channel.close();
 // 4- can reader access here?

      

1, 2, 3 or 4?

No 4 sure because the channel is closed! How about other points?

Thank!

+3


source to share


2 answers


I am summarizing a few notes from a chat conversation with the OP. The OP had a mental model (like most of us) that as soon as a thread writes to a data structure, that data structure is immediately visible to all other threads. In OPs tests using memory mapped files, he confirmed that this turned out to be true on one Intel CPU Intel.

Unfortunately, this is not true, and this is an area where Java can and does show basic hardware behavior. Java was designed to assume that the code is single threaded and can be optimized as such until otherwise stated. What this means will differ in hardware and access point version (and statistics that the hotspot collects). This complexity and running on a single Intel CPU socket overturned the OPs test.

For more information, the following links will help you gain a deeper understanding of the "Java Memory Model". And in particular, synchronization does not just mean "mutual exclusion"; in hardware terms, this also applies to "data visibility" and "instruction ordering". Two topics that single threaded code takes for granted.



Don't worry if it takes time to dive in and you feel overwhelmed at first. At first it was all like this. Java does an amazing job of hiding this complexity if and only if you follow this one simple rule. When a stream reads or modifies a shared data structure, it must be in a synchronized block. That is, both the write stream and the read stream. Obviously, I am oversimplifying, but I follow this rule and the program will always work. Break it down only if you have a very deep understanding of the Java memory model, memory barriers, and how it relates to different hardware (and even then concurrency experts don't even break this rule if they can: single-point is often very much easier and can be unexpectedly fast... Many low latency systems are designed to be mostly single threaded for this reason.)


Direct answer to OP's question. There are no locks in the sample code from the question. No memory barriers, no concurrency controls at all. So the behavior of the read / write interaction will be undefined. They can work, they cannot. They can work most of the time. Intel has the strongest memory guarantees across all processors, as well as running test cases on a single socket. Intel processor will miss many tricky bugs. The sun was caught by this too, before Java 5 and JSR 133 came along (read the article on why Double Checked Locking was broken in Java for more details).

+2


source


You will not get any blocking exceptions from this code or any blocks. File locks work between processes, not between threads. This is where you need sync, semaphores, or ReadWriteLocks. And there is no need to use two channels.



+1


source







All Articles