欢迎来到LYBLaoInB的博客
LYBLaoInB
LYBLaoInB
回首往事,不因虚度年华而悔恨,不因碌碌无为而愧疚

volatile关键字

一、高并发中的可见性,有序性,原子性

二、代码分析volatile关键字

package com.lyb.jmm;

/**
 * @ClassName VolatileTest
 * @Description
 * @Author Lyb
 * @Date 2019/12/4 15:48
 * @Version V1.0
 **/
public class VolatileTest {
    private static volatile int num=0;

    public static void count()  {
        num++;
    }

    public static void main(String[] args) throws Exception {
        Thread[] ts=new Thread[10];

        //线程数组中加10个线程,都对num做1000次加
        for (int i=0;i<10;i++){
            ts[i]=new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i=0;i<1000;i++){
                        count();
                    }
                }
            });
            ts[i].start();

        }
        //join线程
        for (Thread t :ts){
            t.join();
        }
        //输出结果
        System.out.println(num);
    }
}

输出结果为: 多次执行发现结果都是小于等于10000的

分析:

 

 

 如图,因为volatile是会在num改变的时候将信息告知给cpu总线嗅探监听。这个时候线程2发现我的工作内存中也有num这个变量,然后这个变量就失效了。但是如果说T1和T2都对num做了一次++,num在他们的内存中都是1,但是T2中的失效了,就会重新从主内存read并load变量num得到的也是1,随着循环的继续,num++在T2中就被assign成了2但是,此时num++已经执行了三次了,T1,T2中分别++一次,T2读到变量值后再++一次,但是结果却是3。这就是因为volatile关键字没有原子性。再store的时候,变量失效了就不会被store并write到内存中,会少掉对变量操作的记录,这一次num++不具备原子性。如果想要程序具有原子性,要对代码块加sychronized关键字了

 

 

 有序性:

volatile与有序性
多线程通过抢占时间片来执行自己的代码体,所以我们会感觉到线程是同时执行完的,除了引入了时间片以外,由于处理器优化和指令重排等,CPU还可能对输入代码进行乱序执行,比如我们拿到数据要执行写库,查询,删除这三个操作,这就会可能要涉及到有序性的问题了。
volatile可以禁止指令重排,这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。被volatile修饰的变量的操作,会严格按照代码顺序执行接下来我们就说一下为了实现volatile内存语义JMM是怎样限制重排序(包括编译器重排序和处理器重排序)的。

 

posted @ 2019-12-04 16:39  LiuYongbo  阅读(327)  评论(0编辑  收藏  举报
<--将网易云歌单中的id复制到上面的data-id中就可以了 http://music.163.com/playlist?id=3103841025&userid=1698529278 -->