今天正式开始我的面试之旅,因为自己的工作经历原因,平时很少会用JUC相关的处理。今天虽然也问到了,凭着自己看过几本书经历勉强过关,正如赏金的潜台词一样,好运不会眷顾傻瓜的。结合今天面试问题我们深度剖析一下最常见的问题, Volatile和Synchrnized?
秉持着体育老师教过我们鲁迅说过:敏而好学,不会就去看书。作为体育课从不逃课的学生来说,肯定听老师的话,我们就揭开这层窗户纸。
JVM的内存模型我们就不在重复说了,可以看我博客前面的文章,那么CPU Cache模型是什么样的呢?
缓存中又分L1 L2 L3 我们就不画了,关系不大。为什么在CPU和RAM中出现了一个第三者缓存Cache呢? 这里并不是因为CPU花心,而是为了解决CPU直接访问内存效率低下的问题,程序在运行的过程中,会将运算所需要的数据从主内存中Copy一份到Cache中,这样CPU进行计算的时候就可以直接对Cache中的数据进行读取和写入,当运算结束之后,再将Cache到主内存中,CPU通过直接访问Cache的方式替代直接访问主存的方式。极大提高了CPU的吞吐能力。
CPU和主存之间产生了小三,如何解决CPU的缓存一致性问题呢?
- 读取主内存的i到CPU Cache中
- 对i进行加一操作
- 将结果写回到CPU Cache中
- 将数据刷新到主内存中
这个场景下两个线程同时操作 i起始为0 ,那么两次自增就会出现结果为1 的情况实际应该是2 解决这个问题我们两种方式去解决:
- 总线加锁
- 缓存一致性协议 总线加锁过于悲观,我买了一个8核CPU在多线程下你非要我用单核,我的钱又不是大风刮来的 ,怎么可以这样用呢。
缓存一致性最出名的就是Inter的MESI协议。MESI协议保证了每一个缓存中使用的共享变量副本都是一致的,它的大致思想,当CPU在操作Cache的时候,如果发现该变量是一个共享变量,也就是CPU Cache中也存在一个副本会做如下操作
- 读取操作,不做任何处理,只是将Cache中的数据读取到寄存器中。
- 写入操作,发出信号通知其他CPU将该变量的Cache line 设置为无效状态,其他的CPU在进行变量读取操作的时候不得不到主内存中再次获取。
周六在码 未完待续