volatile变量小结

众所周知,volatile是java语言提供的一种稍弱的同步机制,用来确保将变量的更新操作通知到其他线程,如果变量被声明为volatile类型后,编译器和运行时都会注意到这个变量是共享的,因此不会将该变量的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile的变量时总是返回最新写入的值.。
volatile保证可见性
如果某个变量被volatile修饰之后,那么久具备了两层含义:
1.对于多线程操作而言,单个线程对该变量的修改,对其他线程是立即可见的。
因为使用volatile关键字修饰的变量被修改后会被立即刷新到内存,当其他线程读取该变量时,会使其他线程对应的工作缓存的变量无效,重新去内存中读取变量,因此总能读到最新的变量值。

2..禁止进行指令重排序
简单的说,就是在该指令前面的指令一定会先执行,在该指令后面的指令一定是该条指令运行后才能执行,但是该条指令前面的指令可以指令重排序,该指令后面的指令也是可以重排序的

volatile不保证原子性

下面拿一段代码为例

public class VolitileTest {
    public volatile int visitCount = 0;

    public void increase() {
        visitCount++;
    }

    public static void main(String[] args) {
        final VolitileTest test = new VolitileTest();
        for (int i = 0; i < 200; i++) {
            new Thread() {
                @Override
                public void run() {
                    for (int j = 0; j < 10000; j++)
                        test.increase();
                }
            }.start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(test.visitCount);

    }
}

运行结果为1985687,发现并不是200000,其实很容易理解,虽然某个线程修改变量值后会立即将更新的值写到内存,但是并不能保证是原子操作,他只能保证读取的是最新的值。假设某个时刻visitCount变量的值为100,线程1对变量执行加一操作,线程1先读取变量的原始值,然后线程1阻塞了,此时线程2也去读取变量的值,显然此时读到的也是100,然后线程2进行自增操作,将101写入内存,由于线程1已经读取了visitCount的值,并不会再去内存读取一边,此时它恢复运行状态,也执行自增,同样的将101写入内存,此时会发现虽然两个线程都执行了自增操作,但是值却只加了一。

volatile的使用场景

1.对变量的写操作不依赖于当前值

2.该变量没有包含在其他变量的不变式中

3.访问变量时不需要加锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值