(二)死磕java之内存模型(JMM):了解volatile关键字

上一篇我们说了在保证数据一致性方面需要满足三个特性原子性 可见性 有序性

在java当中volatile这个关键字有如下特性

  1. 保证可见性
  2. 不保证原子性
  3. 禁止指令重排

可见性

public class VolatileApp{
    private static boolean initFlag = false;
    public static void main( String[] args ) {
        //线程A
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!initFlag){
                }
                System.out.printf("initFlag-----"+initFlag);
            }
        }).start();
        //线程B
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("aaaaaaa");
                initFlag = true;
                System.out.println("aaaaaaa");
            }
        }).start();
    }
}

image.png

运行结果显而易见,线程B中initFlag修改值为true后,线程A并没有接收到这个信息,要让A能够立即指导initFlag修改后的值,加入volatile关键字并能解决这个问题,这就是一个很典型的内存可见性问题的场景。

//修改代码如下
private volatile static boolean initFlag = false;

不保证原子性

首先我们来看下面这一句代码

public volatile int incre = 0;
public void increase() {
        incre ++;
    }  

我们开启线程运行increase()方法,假如10个线程,循环运行100次,理想状态下,得到的结果incre打印出来的结果会是1000,可是实际运行出来的情况肯定不是这样的,一般都会小于1000这个数。
我们说了volatile保证变量在主内存的可见性,在值修改后会通知其他线程去获取最新的值,可是在这个地方incre++这个操作并不是一个原子性操作,这里解释一下,自增操作是不具备原子性的,它包括读取变量的原始值、进行加1操作、写入工作内存。

你可能感兴趣的:((二)死磕java之内存模型(JMM):了解volatile关键字)