Volatile and CAS总结

前言:

今天被al小哥哥问了几个问题,回答的问题在很大程度上代表你对这个问题的深刻理解。然而 自己...真的真的 没有把一些东西真正的理解透啊。

知识点不在于 看了多少遍,在于不断的 系统的去总结、分析、理解。

本着对volatile的理解,提出来几个问题?

1.volatile怎么实现的可见性?-->MESI协议

2.cas怎么实现的可见性? -->也是用的MESI 协议

3.volatile避免指令的重排序是通过内存屏障解决的,那他还和MESI有什么关系?MESI也用了内存屏障? 

1.1volatile:(可见性、有序性)注:对于单次的volatile变量操作是原子性的,但是连续对volatile操作不是原子性的
一:对于一个volatile变量,写进去的时候 会把工作内存里面的 值刷新到 主内存里面;而 读volatile变量的时候 ,如果发现这个变量是一个volatile变量的话,会使这个变量失效,重新再从主内存里面读取进来。这个回答是不是太.....肤浅。

《java并发编程艺术》说,volatile在编译的时候会生成一个lock前缀。然而 lock前缀到底有什么作用呢?对于此理解的真的不够深刻啊。 多线程编程,在操作系统里面是用户态的,通过操作系统的 用户态线程和内核线程之间的对应,可以将用的线程 映射到其它处理器上面去,(其实线程内的工作内存是 cpu寄存器和cpu缓存的抽象)(那么问题出现了 --------》

如果一个线程A在cupu1上面,线程B在cpu2上面,假如 cpu1和 cpu2同时更改变量X,两个处理器各自执行各自的,然后放到各自的缓存在继续执行下条指令,那么 不是乱套了么?所以,必须想办法 只能有一个处理器在操作 一个共享变量,而让另一个处理器中缓存了该变量的值无效!!所以前辈们想出了两个方案:

1.锁住总线:当一个处理器输出一个信号(Lock#),然后别的处理器就不能访问共享变量。 这个方法简单粗暴啊。所以人们肯定得想个别的办法把。

2.锁住缓存:大白话的思想就是 cpu1 操作了一个共享内存数据,同时通知其它的cpu,让他们的对于这一个共享内存的缓存无效!如果其它cpu在要操作这个共享内存的数据的话,得重新读缓存。

说实话《java并发编程艺术》对于缓存一致性协议讲的有点生涩,看了很多遍对于这一概念还是模糊,于是找度娘把

---->缓存一致性协议:MESI 协议,就是给各个处理器制定了一套游戏规则:

M (modeified) 被修改的: 处于这个状态的数据只存在当前处理器的缓存当中,并且改变了原来的值

E(exclusive) 独占的: 处于这个状态的数据只存在当前处理器的缓存当中,并且和内存中的值 一样,没有被修改

S (shared)共享的: 处于这个状态的数据在多个cpu缓存中的值一样,并且和内存中的值一样

I (invalid)无效状态: 处于贝格cpu中的缓存已经无效。

如果当前cpu要读数据了,如果是I状态,那么读进数据来之后,把状态改成S。其它的状态可以直接读就可以,在此之前,必须监听一下别的cpu缓存对于此数据的状态,如果别的cpu存在M状态,那就等那个cpu把数据存到内存中然后再去读。

如果说当前cpu要写数据了,只有M 和E 状态才能执行,否则发出一条指令,至其他的cpu的 缓存置为无效,然后把状态改为M.

再回到上文,volatile在总线上发出的lock前缀,会声言出lock#信号,最近的lock# 信号使用的是所缓存的。所以lock前缀什么作用,我们可以总结成两点

1.让该缓存行刷新到内存中去

2.使其它处理器的缓存的数据无效 

1.2:CAS 

/*

如果两个处理器,同时对一个数据进行CAS,那么会怎么做?同时对一个数据进行CAS,也就是说要更改本处理器中缓存的数据,更改状态为M或者E,成功了之后是其他的处理器中的数据无效 变成I. 然而怎么决定让哪一个处理器更改缓存数据呢? 这个就让ring bus仲裁吧。

*/

2:内存屏障

硬件层 两个内存屏障 load barrier 、store barrier

有两个功能:1、禁止屏障前后的重排序 2、强制把写缓冲区的的数据写入内存

LoadStore屏障: (Load1 LoadStore Store2) 在store2以及后续的刷入内存前,先进行Load1把数据读出来

LoadLoad屏障:(Load1 LoadLoad Load2)在Load1以及后续读数据前,先进行Load1把数据读出来

StoreLoad屏障(万能屏障):(Store1 StoreLoad Load2)在Load2读数据之前,先进行store1写操作,使其对所有处理器可见

StoreStore屏障:(Store1 StoreStore Store2)在store2及后续写操作前,先进行store1写操作,使其对所有处理器可见

volatile的内存屏障:

volatile写操作: 前面插一个storestore屏障 ; 后面插一个storeload屏障

volatile读操作: 后面插一个loadload屏障,后面插一个loadstore操作

3.happens-before

四个规则:

程序顺序规则:一个线程中的每个操作都happends-before于后续操作

监视器锁原则:对一个锁的解锁 happends-before 后续对这个锁的加锁

volatile变量原则:前一个volatile变量的写操作happends-before后面的读操作

传递性原则:Ahappens-beforeB, Bhappends-beforeC,那么Ahappends-beforeC

注解:任何带有lock前缀的指令都有 内存屏障的作用

所以,还是静下心,调整一下心态,这几天确实被春招弄的有点浮躁了。没有根基的高楼注定是虚幻的,所以基础真的很重要呀

以上笔记如果有错欢迎指正呀~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值