zoukankan      html  css  js  c++  java
  • volatile 和 缓存一致性协议 mesi的关系

    在Java中,volatile是个很高层面的规范,保证了指令不会被重排序+对volatile变量的写使得当前cpu缓存中的所有变量写回到主存中,从而保证了内存可见性。

    具体的实现是靠JVM和cpu(还有操作系统?)合作实现的,不管cpu有没有mesi协议,用了volatile,JVM都会保证可见性,只不过实现方式是不一样的。

    有个问题就是:mesi似乎已经保证了线程之间的可见性,那么在实现了mesi协议的cpu上,volatile关键字其实是不是没用的?

    答案是:还是有用的,就算在实现了mesi的cpu上,volatile一样不可或缺。除了禁止指令重排序的作用外,由于mesi只是保证了L1-3 的cache之间的可见性,但是cpu和L1之间

    还有像storebuffer之类的缓存,而volatile规范保证了对它修饰的变量的写指令会使得当前cpu所有缓存写到被mesi保证可见性的L1-3cache中。(具体的实现,以X86体系为例,

    volatile会被JVM生成带lock前缀的指令)。

    扯两句远的:

    1、i++的问题是写更新丢失的问题,跟现在说的没关系,要用cas解决。

    2、cas其实不是原子性操作,要读一次,再写一次。但是可以用MESI实现原子性:读一次发现是目标值,写的时候判断是不是I就可以。mesi实现其他原子性操作也是这个思路。

    3、从2可以看出,悲观锁和乐观锁并不是对立的两件事,以数据库版本号实现乐观锁为例,update要锁行,这个又是悲观锁,而锁行(可能)要用cas去操作volatile变量,这又是乐观锁,然而底层mesi实现原子性的时候,写的时候需要知道现在的缓存行有没有失效,这就一定需要cpu核心之前有一个同步锁,这个又是悲观锁。所以纠结于名词是没有意义的,知道到底发生了什么事情更重要。

  • 相关阅读:
    leetcode 673. 最长递增子序列的个数 java
    leetcode 148. 排序链表 java
    leetcode 98. 验证二叉搜索树 java
    leetcode 29. 两数相除 java
    leetcode 234. 回文链表 java
    Valid Palindrome LeetCode Java
    Single Number II LeetCode Java
    Single Number LeetCode java
    Search in Rotated Sorted Array II LeetCode Java
    Search in Rotated Sorted Array leetcode java
  • 原文地址:https://www.cnblogs.com/chuliang/p/8206748.html
Copyright © 2011-2022 走看看