volatile关键字小结

Java 提供了一种稍弱的同步机制,即 volatile 变量,用来确保将变量的更新操作通知到其他线程。可以将 volatile 看做一个轻量级的锁,但是又与锁有些不同:
1. 对于多线程,不是一种互斥关系
2. 不能保证变量状态的“原子性操作”

在没有用volatile关键字修饰的demo

/**
 * Volatile 关键字:当多线程操作共享数据时,可以保证内存数据的可见性,
 * 相较于synchronized来说是一种比较轻量级的同步策略。
 * 注意:
 * 1. Volatile不能保证变量的原子性。
 * 2. 不具备互斥性
 * Created by 吴海飞 on 2017-1-23.
 */
public class TestVolatile {
    public static void main(String[] args){
        volatileDemo volatileDemo = new volatileDemo();
        new Thread(volatileDemo).start();

        while (true){
            if(volatileDemo.isFlag()){
                System.out.println("------------------");
                break;
            }
        }

    }
}

class volatileDemo implements Runnable{

    private boolean flag = false;

    @Override
    public void run() {

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
        flag = true;
        System.out.println("flag=" + isFlag());
    }
    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

}
  • 代码运行后会出现这种状况如下图所示:

  • 出现这种状况的原因是:
    主线程与子线程并发执行,在子线程拿到flag=false的同时,主线程也拿到了flag=false,之后子线程将flag变为true,并打印出flag,结束线程。主线程因为读取到的flag = false,所以一直处于死循环状态中无法结束线程任务。

  • 具体分析如下图所示:
    这里写图片描述

  • 将flag变量设置成 volatile的,这样问题就解决了。
    当子线程将flag关键字改变时,将flag从子线程的缓冲区写入到内存中,这样主线程读到的flag变成true了,所以问题就解决了。

原文地址:https://www.cnblogs.com/haifeiWu/p/9079586.html