volatile关键字简单总结

什么是缓存一致性

说到volatile必须了解的是缓存之间的一致性,
假设有双核cpu。在CPU1运行线程1,在CPU运行线程2,两个线程共享1个变量为TEMP。TEMP并未被volatile修饰,此时线程1对TEMP进行写操作,线程2对TEMP只有读取操作。无论线程1如何修改TEMP线程2都不会感知到。原因:线程1和线程2维护各自的cache而cache中维护各自的TEMP。线程1有写操作,在写入成功会把TEMP从cache刷新到主存中。而线程2不会从主从中拿数据,只会永远从cache里面拿数据,因为线程2只有读取操作(java优化机制)

如何解决缓存不一致?

  • 加总线锁 (太耗性能)
  • 使用缓存一致性协议(java中可以加volatile)

java线程与缓存之间的关系
在这里插入图片描述

happends before原则

1.在同一个线程中,书写在前面的先于书写在后面的
2.unlock必须发生在lock之后
3.volatile修饰的变量,对一个变量的写操作先于读操作
4.传递规则:操作A先于B,B先于C那么A先于C
5.线程的启动规则:start方法先于线程执行操作
6.线程的中断规则:interrupt动作必须发生在捕获之前
7.对象销毁规则:对象的初始化必须发生在finalize之前
8.线程的终结规则:线程的所有操作必须发生在线程死亡之前

代码模拟缓存不一致现象

实现目标:

一个线程修改initSize,一个线程监听修改

如下代码所示:在reader线程和writer线程共享变量initSize。而期待当writer修改了initSize此时reder会读取到变化。但是reder基本没有读取到变化。在writer写入时确实将initSize刷新到主存了但是reader并未从主存拿取数据。因为在reder中对initSize只有读取操作,java对这种读取操作优化为:只在缓存中拿数据不会再去主存拿取数据所以导致initSize的值很少概念或基本不变。

如何解决?可以使用volatile关键字,它可以保证数据的可见性,writer只要修改了initSize。此时reder读取缓存中的initSize就会失效,必然去主存拿取数据。

public class VolatileDemo {
    private static int initSize = 0;
    private static final int MAX =5;
    public static void main(String[] args) {

        new Thread(()->{
            int local = initSize;
            while(local < 5){
                if(local != initSize){
                    System.out.println("initSize 已经被更新为 "+initSize);
                    local = initSize;
                }
            }
        },"Reader").start();

        new Thread(()->{
            int temp = initSize;
            while(temp < MAX){
                System.out.println("更新 initSize 为"+ (++temp));
                initSize = temp;
                try {
                    Thread.sleep(500L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"Writer").start();

    }
}

总结

volatile只能保证可见性和顺序性,因为共享资源的安全性问题无法保证原子性

使用场景

1.状态量标记

作为boolean类型的标记

2.保证线程屏障前后的一致性

voilatile修饰的变量作为屏障,屏障后面的肯定发生在前面的后面。但是屏障前面的代码间的具体顺序就无法保证了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值