Search code examples
javamultithreadingvolatile

Would a thread handling a subsequent network request be guaranteed to see the value of a volatile variable written during a previous request?


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.


Solution

  • I found my answer!

    Section 17.4.3 of the Java Language Specification states the following:

    Sequential consistency is a very strong guarantee that is made about visibility and ordering in an execution of a program. Within a sequentially consistent execution, there is a total order over all individual actions (such as reads and writes) which is consistent with the order of the program, and each individual action is atomic and is immediately visible to every thread.

    In the Java Memory model, "actions" refer to inter-thread actions, which include volatile writes. This paragraph guarantees that any Java implementation that conforms to the JLS guarantees that volatile writes will be immediately visible to other threads. In the example in the opening post, this paragraph guarantees that the volatile read can not be ordered before the volatile write.