What does "subsequent read" mean in the context of volatile variables?

Trismegistos :

Java memory visibility documentation says that:

A write to a volatile field happens-before every subsequent read of that same field.

I'm confused what does subsequent means in context of multithreading. Does this sentence implies some global clock for all processors and cores. So for example I assign value to variable in cycle c1 in some thread and then second thread is able to see this value in subsequent cycle c1 + 1?

Peter Cordes :

It sounds to me like it's saying that it provides lockless acquire/release memory-ordering semantics between threads. See Jeff Preshing's article explaining the concept (mostly for C++, but it main point of the article is language neutral and about the concept.)

In fact Java volatile provides sequential consistency, not just acq/rel. There's no actual locking, though. See Jeff Preshing's article for an explanation of why the naming matches what you'd do with a lock.)


If a reader sees the value you wrote, then it knows that everything in the producer thread before that write has also already happened.

This ordering guarantee is only useful in combination with other guarantees about ordering within a single thread.

e.g.

int data[100];
volatile bool data_ready = false;

Producer:

data[0..99] = stuff;
 // release store keeps previous ops above this line
data_ready = true;

Consumer:

while(!data_ready){}     // spin until we see the write
// acquire-load keeps later ops below this line
int tmp = data[99];      // gets the value from the producer

If data_ready was not volatile, reading it wouldn't establish a happens-before relationship between two threads.

You don't have to have a spinloop, you could be reading a sequence number, or an array index from a volatile int, and then reading data[i].


I don't know Java well. I think volatile actually gives you sequential-consistency, not just release/acquire. A sequential-release store isn't allowed to reorder with later loads, so on typical hardware it needs an expensive memory barrier to make sure the local core's store buffer is flushed before any later loads are allowed to execute.

Volatile Vs Atomic explains more about the ordering volatile gives you.

Java volatile is just an ordering keyword; it's not equivalent to C11 _Atomic or C++11 std::atomic<T> which also give you atomic RMW operations. In Java, volatile_var++ is not an atomic increment, it a separate load and store, like volatile_var = volatile_var + 1. In Java, you need a class like AtomicInteger to get an atomic RMW.

And note that C/C++ volatile doesn't imply atomicity or ordering at all; it only tells the compiler to assume that the value can be modified asynchronously. This is only a small part of what you need to write lockless for anything except the simplest cases.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=36185&siteId=1