Java多线程之测试volatile关键字

volatile的两个作用
阻止指令重排序
内存可见性(即每次变量的读取都从主存中读取,不从cpu高速缓存读取

volatile变量自增与线程安全性的测试

static volatile int count = 0;
   public static void main(String[] args) {

        final long next = System.currentTimeMillis()+2000;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while (System.currentTimeMillis()<next);//自旋,尽量使线程同一时间执行count++
                count++;
            }
        };

        for (int i = 0; i < 40; i++) {
            new Thread(runnable).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //测试最终输出结果可能为38,39,40等
        System.out.println(count);
    }

结论:volatile关键字无法保证volatile变量操作(非单独读写操作)的原子性,即volatile变量的操作不是线程安全的
以count++为例,这里可以分成3步原子性操作
1.从主存读取count值
2.执行+1操作(A线程执行此操作,同时B线程执行读取操作,此时A线程还没执行操作3,而B线程开始执行操作2,结果造成count值多加一次
3.将+1后的值写回主存

volatile内存可见性测试

   
    static int i = 0;
    static int count = 0;

    public static void main(String[] args) {
		//main线程sleep的时间,从3开始线程听不下来,该值小于2的时候线程会停止
		//如果静态变量count和i只要有一个声明为volatile变量,无论该值多大,线程都会停止
		//静态变量不加volatile,该线程停止临界值值会随着循环方法里代码执行效率而改变
        long waitTime = 3;

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while (i<=0){
                    count++;
                }
            }
        };

        for (int i = 0; i < 3; i++) {
            new Thread(runnable).start();
        }

        try {
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        i = 1;
        System.out.println(count);

    }

为什么不加volatile关键字,main线程设置不同的休眠时间,得到的结果会不同呢?

初步理解:

不加volatile的话,run方法体里的循环代码在运行期有可能成为热点代码被JIT编译器编译成机器码,因此时间临界值内循环体内的代码还未成为热点代码,可以从主存读取main方法修改i后的值,成为热点代码被编译成机器码后就不在从主存读取i的值

加volatile的话,run方法体的循环代码在运行期也会被JIT编译器优化,但优化后的机器码依然会从主存中读取i的值,因此循环体可以停止

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值