volatile

What is the volatile keyword useful for?

https://stackoverflow.com/questions/106591/what-is-the-volatile-keyword-useful-for

java 1.7 memory model

1.用于线程停止的flag

因为volatile被写操作之后,读出来的都是从main memory读最新的值。

Without volatile, the thread running the loop may never see the change to close.

public class Foo extends Thread {

  private volatile boolean close = false;

  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}

2.单线程环境使用volatile无意义

在一写多读的环境下很好使用,就像上面线程停止的flag,但是多个写者的情况下仅靠volatile来使一个变量在多个线程合法共享。

volatile keyword is an ideal way to maintain a shared variable which has 'n' number of reader threads and only one writer thread to access it.

We can't make use of volatile keyword solely, to satisfy a shared variable which has more than one writer thread accessing it.

https://stackoverflow.com/a/49098807/5646921x

3.单例模式

如果不使用volatile的话,由于会指令重排出现问题。

Although it checks the value of instance once again within the synchronized block (for performance reasons), the JIT compiler can rearrange the bytecode in a way that the reference to the instance is set before the constructor has finished its execution. This means the method getInstance() returns an object that may not have been initialized completely.

https://stackoverflow.com/questions/106591/what-is-the-volatile-keyword-useful-for/22009557#22009557

4.关于指令重排

可能被指令重排序为:

不用volatile的话,A线程首先进入synchronized进行对象创建,此时指令重排,先分配了地址,在调用构造函数的时候,B线程调用getInstance,此时instance不为null,会返回一个未被构造完全的instance。

volatile会禁止指令重排,所以这种情况不会发生。

老的java内存模型中,volatile修饰的变量写操作会和其他非volatile变量进行重排。

old memory model allowed for volatile writes to be reordered with nonvolatile reads and writes, which was not consistent with most developers intuitions about volatile and therefore caused confusion.

在新的内存模型中,他说的是不容易和非volatile进行重排,还会保证对volatile field写之后,另外一个线程读该field的时候会读到最新值。

Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.

具体参考:

(设计模式)单例模式的双重检查

Volatile: why prevent compiler reorder code

JSR 133 (Java Memory Model)

Last updated

Was this helpful?