volatile的使用及作用

volatile

保证线程可见性

static boolean checkType = true;
    public static void main(String[] args) throws Exception {
        new Thread(()->{
            while(checkType){

            }
            System.out.println("thread end");
        }).start();

        Thread.sleep(100);// 确保现场可以开始执行

        checkType = false;//更改值  希望thread能够结束

        /*
            result: 线程一直执行  无法结束
            原因是因为 线程之间变量是不可共享的
         */
    }
static volatile  boolean checkType = true;
    public static void main(String[] args) throws Exception {
        new Thread(()->{
            while(checkType){

            }
            System.out.println("thread end");
        }).start();

        Thread.sleep(100);// 确保现场可以开始执行

        checkType = false;//更改值  希望thread能够结束

        /*
            result: 线程可以结束
            变量加上修饰符 volatile 可以让线程之间变量可见,所以变量值变化了  其它线程 是可以读到的
         */
    }

禁止指令重排序

什么叫指令重排序

编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段。

也就是说,对于下面两条语句:

int a = 10;

int b = 20;

在计算机执行上面两句话的时候,有可能第二条语句会先于第一条语句执行;

编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。也就是说:在单线程环境下,指令执行的最终效果应当与其在顺序执行下的效果一致,否则这种优化便会失去意义。这句话有个专业术语叫做as-if-serial semantics (as-if-serial语义)

重排序对多线程的影响在多线程程序中,对存在依赖重排序,可能会改变程序的执行结果。

private static int a,b,x,y;
    private  static int  count=0;
    public static void main(String[] args) throws Exception {
        for(;;){
            count++;
            a=0;      b=0;
            x=0;      y=0;
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    a=1;
                    x=b;
                }
            });

            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    b=1;
                    y=a;
                }
            });

            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();

            /*
                   代码分析,两个线程开始运行,无论是thread1 还是thread2先运行,a=1 或者 b=1先运行,x和y 必定有一个为1
                   thread1开始执行并走完, 那么 a=1,x=0;b=1,y=1;   0  1;
                   thread2开始执行并走完,  那么 b=1,y=0,a=1,x=1;   1 0;
                   thread1开始执行,a=1 thread2开始执行 b=1, 继续 x=b; y=a;  则 a=1,b=1,x=1,y=1;  1  1
                   绝无可能 x y  同时为0
             */

            if(x==0 && y==0){
                System.out.println(count+":"+x+","+y);
                break;
            }
            /*
                result:  117523:0,0
                结论:有可能会出现这种情况x=0,y=0;
                原因是指令重排序 导致thread1中的x=b;  thred2中的y=a; 先执行完毕,才执行了a=1   b=1
             */

        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值