开发者

Total Order between !different! volatile variables?

开发者 https://www.devze.com 2022-12-25 12:41 出处:网络
Consider the following Java code: volatile boolean v1 = false; volatile boolean v2 = false; //Thread A v1 = true;

Consider the following Java code:

volatile boolean v1 = false;
volatile boolean v2 = false;

//Thread A
v1 = true;
if (v2)
    System.out.println("v2 was true");

//Thread B
v2 = true;
if (v1)
    System.out.println("v1 was true");

If there was a globally visible total order for volatile accesses then at least one println would always be reached.

Is that actually guaranteed by the Java Standard? Or is an execution like this possible:

A: v1 = true;
B: v2 = true;
A: read v2 = false;
B: read v1 = false;
A: v2 = true becomes visible (after the if)
B: v1 = true becomes visible (after开发者_JAVA百科 the if)

I could only find statements about accesses to the same volatile variable in the Standard (but I might be missing something).

"A write to a volatile variable (§8.3.1.4) v synchronizes-with all subsequent reads of v by any thread (where subsequent is defined according to the synchronization order)."

http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.4

Thanks!


The 4 actions, volatile read/write of v1/v2, are all synchronization actions. An execution has a synchronization order over them, which is a total order. The order must keep the program order of each thread.

That makes reasoning very easy. Obviously at least for 1 of the 2 variables, the write to it is ordered before the read from it, in the 'synchronization order'. Therefore, the write 'synchronizes-with' the read. Therefore, the write 'happens-before' the read. Therefore, the write is visible to the read.


I think the quote answers your question more than you realize it does.

The write to v2 by thread B in line #2 is "seen" by thread A when it attempts to read the variable.

I've bolded the key part of the quote:

"A write to a volatile variable (§8.3.1.4) v synchronizes with all subsequent reads of v by any thread ..."


The third line in your execution is not possible, due to the fact that v2 is volatile.

If v2 were not volatile, thread A could see a locally-cached copy of v2 that was still false.

Since v2 is volatile, however, every read will go directly to main memory, and will thus see the most recently-written value.

That said, I don't believe there are any specific ordering guarantees between accesses to different global variables, but I also don't believe it makes a difference in your example.


Volatile variables in Java are always sequential consistent. So their execution is consistent with a sequential execution of all volatile loads and stores. In this sequential execution there is a total order over all loads and stores (so loads and stores over different addresses; not just over a single address).

So the execution in your example is not allowed.


Well...by the definition of volatile if v2 was set to true by B, then A can't read it as false.

volatile makes data types and references work as expected when threading when doing single opeartions (so ++ and -- don't work!)


Briefly: At least once will be printed, because the two volatile operations can not be reordered.

I do not know where it is written about in the specification, but on the Doug Lea site have a table which operations can reorder and what does not. ( http://gee.cs.oswego.edu/dl/jmm/cookbook.html )


This situation is not possible, because read is initialization happens before thread start

WRONG!

A: v1 = true;
B: v2 = true; 
A: read v2 = false; // initialization happens before thread start
B: read v1 = false; // initialization happens before thread start

You situation possible if only in this situation, but it is not possible because v2 and v1 is volatile and write to v1 must be before read v2 AND write to v2 must be before read v1

WRONG!

volatile boolean v1 = false;
volatile boolean v2 = false;

//Thread A
if (v2)    //read v2
   System.out.println("v2 was true");
v1 = true; //write to v1

//Thread B
if (v1)    //read v1
    System.out.println("v1 was true");
v2 = true; //write v2
0

精彩评论

暂无评论...
验证码 换一张
取 消