zoukankan      html  css  js  c++  java
  • 缓存一致性与可见性

    缓存一致性与可见性

    什么样的数据会存入缓存?

    编译器或CPU可以明确知晓的,可能被经常访问的数据。例如一个在循环体中的变量,因为这个变量需要经常访问,如果每次都从主存中拿,那就太慢了。

    缓存一致,是跟谁一致?

    是跟主存一致,当主存中的对应数据发生变动的时候,CPU中的缓存也会随之变动。例如Cache中缓存了变量x的值,当主存中的x的值变动的时候,Cache中的值也会刷新。“刷新”可能是将该值标记为“失效”,下次需要时从主存拉取,或是直接用新值覆盖。

    主存的数据变动是如何被监听到的?

    Bus Snooping。总线窥探,只要监听总线操作就可知道其他CPU对主存的访问情况。例如监听到x变量的写操作,那就表明x变量的值有变动。

    高速缓存一致这些操作谁来实现?

    底层硬件实现,现代计算机都有提供此功能。

    那这样是不是已经有了可见性?

    没有,当然如果可见性指的是“当主存值发生变化的时候,Cache可以看到”,那确实是实现了。问题是可见性不是这么定义的,它说的是“当一个线程对一个变量进行修改时,其他线程都能够看到”。

    这两种表述方式有什么不同?

    其实就是“一个线程对变量A的修改” ≠ “主存值发生变化”。也就说,修改变量的值后,修改的只是缓存中的值,不会马上写入主存。

    为什么不马上写入主存?

    因为慢。所以这个写操作会被重排序到后面,这个操作还是会执行的,只是优先级没那么高。

    那是不是马上写入主存就能实现可见性呢?

    是的,只要马上写入主存,由于底层提供“高速缓存一致性”,所以当内存中的变量发生变更时,其他CPU的缓存也会随之更新。那这样可见性就有了。

    那么如何让它马上写入主存呢?

    防止重排序就可以了,这样写入内存的操作就会被立即执行。一般就是加内存屏障。synchronized、volatile都依赖内存屏障。

    什么时候需要可见性?

    正常的程序变量一般都不需要可见性。除非这个变量可能被多个线程同时访问,且你需要用这个变量来协调线程操作。那这时候这个变量才需要具有可见性。这时候如果不保证可见性,就很可能出现奇怪的问题,即有时可以正确执行,有时又不行。为什么呢?因为有时候,这些线程刚好在同一CPU上执行,访问的是同一个Cache,自然就能得到正确的,也就是最新的值。但是,大多数情况不是这样,多个线程会在多个CPU上执行,如果不保证可见性,就可能得到过期的值。然后你就会很奇怪,明明看日志打印,已经改了啊,为什么其他线程还是没反应过来呢?

    插一句

    其实缓存一致性和可见性的问题,都是由多CPU的引发的,就是因为每个CPU都有一个Cache,所以才有了这一堆的问题。

  • 相关阅读:
    格子刷油漆【动态规划问题】—NYOJ 980
    Throughput Controller
    CSV Data Set Config 详细使用说明
    nmap使用笔记
    记三个有趣的漏洞
    Windows添加右键新增.md文件
    文件上传绕过WAF
    bypass_safedog
    漏洞挖掘之爆破的艺术
    特殊后缀上传(为什么用白名单不用黑名单)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/10989503.html
Copyright © 2011-2022 走看看