I have this theoretical question about the Java Memory Model. Suppose I have a server with these two request handlers in the following class:
class MyHandlers {
volatile int someFlag = 0;
String handleFirstRequest() {
someFlag = 1;
return "Hello!";
}
String handleSecondRequest() {
return "value of someFlag: " + someFlag;
}
}
I also have a client. My client sends a network request that triggers executing handleFirstRequest. The client waits until the request completes. Once the first request completes, the client sends the second request that triggers handleSecondRequest.
Question: How does the Java Memory Model prevent the response to the second request from being "value of someFlag: 0"?
Notes: I understand that, in practice, the thread handling the second response will always see someFlag as 1.
If I read the JMM correctly, there is a synchronization order that is a total order, which would order the volatile read and the volatile write (someFlag = 1) in my example. If the read is subsequent to the write, then the read will see the write. Is it possible to have a case where the write is subsequent to the read? In this case, the write does not synchronizes-with the read, and there would be no happens-before relationship between the write and the read. This would lead the thread handling the second request to see someFlag as 0. Where does my understanding go wrong?
Additional thoughts (2020 Mar 2): The JMM does not refer to the concept of time. Synchronization actions are ordered according to synchronization order, but nothing in the JMM says that synchronization order is the same as order of actions sorted by time. This suggests a Java implementation may order the read of someFlag before the write even though the read occurred after the write according to the clock. It seems like the JMM only guarantees that if the volatile read is ordered after the volatile write, then writes before the volatile write are visible to reads after the volatile read.