开发者

Reorder normal field around volatile field

开发者 https://www.devze.com 2023-02-09 13:29 出处:网络
Based on What does volatile do? http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#incorrectlySync

Based on

What does volatile do? http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#incorrectlySync

and

New guarantees for volatile http://www.ibm.com/developerworks/library/j-jtp03304/

class VolatileExample {
  int x = 0;
  volatile boolean v = false;
  public void writer() {
    x = 42;
    v = true;
  }

  public void reader() {
    if (v == true) {
      //uses x - guaranteed to see 42.
    }
  }
}

It seems that.

1a) write to non-volatile variable x 
1b) write to volatile variable v

1a can never moved pass 1b

I was wondering, if I modify the source code to the following

class VolatileExample {
  int x = 42;
  volatile boolean v = true;
  public void writer() {
    v = false;
    x = 0;
  }

  public void reader() {
    if (v == true) {
      //uses x - guaranteed to see 42?????
    }
  }
}

Can the following sequence be permuted?

2a) write to volatile variable v
2b) write to non-volatile variable x

I was wondering, can 2b ever move before 2a? This is because if 2b able to move before 2a, reader can no longer guaranteed to see 42 within if block.

I feel 2b can be move befor开发者_运维百科e 2a based on the following information.


http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering

Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire.


This means that any memory operations which were visible to a thread before exiting a synchronized block are visible to any thread after it enters a synchronized block protected by the same monitor, since all the memory operations happen before the release, and the release happens before the acquire.


and Roach Motels and The Java Memory Model

volatile_v = true;      <-- monitor release
non_volatile_x = 42;
(volatile_v will act as a roach motels, and it is fine for non_volatile_x to move into roach motels)


non_volatile_x = 42;
volatile_v = true;      <-- monitor release
(volatile_v will act as a roach motels, and it is not OK for non_volatile_x to move out from roach motels)


Well we know that a write to a volatile variable can't be reordered with respect to any previous read or write (as of Java5), but this isn't true the other way around. So reordering the program to x = 0; v = false; would be correct as I understand it.

After we write to v we're guaranteed that when reading v that every action that happened before writing to v will be visible, but it doesn't say anything about actions AFTER writing to v - those may or may not have happened and can even be reordered to happen before v is written to.


There is two parts to volatile, the order of instructions and the "flushing" of writes.

The order of the instructions won't change, but there can be any delay between two pieces of code so in the second case x it might be 42 but it could be 0. My guess is you will see 0 more often.

Depending on your architecture, this could be more likely than on other systems, so testing it on one machine finding it is 42, doesn't mean that to it will always be on another machine.


As I understand the new memory model, once a volatile value is flushed to main memory, all other variables that can be seen by the flushing thread must also be flushed. But a consequence of this is that your 2b can't be re-ordered by the VM to before 2a since this would violate the 'happens-before' ordering implicit in the code.


I don't think you have that guaranteed since the class instance field x is not encapsulated and as package-visible can be changed by another thread. Making the x variable volatile would solve that issue and guarantee visibility by all threads.


Statement 2b (write to non-volatile variable x) can be moved before statement 2a (write to volatile variable v), i.e., it is possible that another thread sees v==true and x==0).

Note, that even without reordering another thread might see these values!

Assume that an instance of VolatileExample has been created and initialized. Thread T1 executes method reader on that instance. It sees v == true and gets interrupted by the scheduler. A second thread invoking method writer could now execute the assignments v=false and x=0. When T1 resumes and reads x, it might read the value 0 (but does not have the guarantee to see 0). If it sees the value 0 then we have the situation, that T1 sees v==true and x==0. To T1 it looks as if the two statements have been reordered. As this state can be observed without reordering, it makes sense that reordering is actually allowed.

0

精彩评论

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