Volatile

先看一段代码

public class VolatileNoAtomic extends Thread{
    private static int count=0;
    private static void addCount(){
        for (int i = 0; i < 1000; i++) {
            count++ ;
        }

        System.out.println(count);
    }


    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    VolatileNoAtomic.addCount();

                }
            }).start();
        }
    }
}

输出结果

1000
2023
2127
3127
4127
5127
6127
7127
8127
9127

每次运行的结果都不一样
原因:在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。

而有一个很好的解决方法,就是加上Volatile关键字

private static volatile int count=0;

但是也会有瑕疵

2000
3000
2000
5000
4000
6000
7000
8000
9162
9662

原因是指定了Volatile,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取,但是,Volatile修饰的变量不具有原子性!每一个线程都有一个线程栈,如图:

这里写图片描述

而JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新的,如果线程1,线程2同时load到count=5,线程1进行+1操作,那么count就变成6,并写入到主内存中,由于线程2已经完成了了load,他得到的count=5,而不是6,所以最终的结果是6。

解决方法
将count声明为AtomicInteger,
private static AtomicInteger count=new AtomicInteger(0);
private static void addCount(){
for (int i = 0; i < 1000; i++) {
count.incrementAndGet();
}

那么这样做就能让count的每一次操作都是原子的。
结果:

3315
3877
4000
3315
5000
6544
7000
8000
9000
10000

每次得到的结果都是10000

**

总结:Volatile能使变量在进程中可见但是不具备原子性。

**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值