zoukankan      html  css  js  c++  java
  • 写缓冲器 ,无效化队列 存储屏障 加载屏障

    为什么会有写缓冲器 ,无效化队列 ?

    先来看一下什么是缓存一致性协议

    核心思想:如果变量是共享变量,当其他CPU修改这个变量的时候,发出信号将其他CPU的变量置为失效状态,其他CPU再使用这一变量的时候会从内存中加载这一变量。

    修改共享数据的时候,发现相应 缓存行的状态是S, 就是共享,说明其他cpu也有副本, 这时候要发 无效 的通知出去广播给其他cpu把缓存里面的值为无效(Invalid)状态,然后待收到各个缓存的(Invalid ack)已经完成无效状态修改的回应之后,再把自己的状态改为Exclusive,之后再进行修改,修改后再改为Modified状态,数据写入缓存行。

    这样会有一个缺点,CPU需要在等待所有的Invalid ack之后才会进行下面的操作。这会让CPU产生一定的阻塞,无法充分利用CPU。这个时候就出来了写缓冲器无效队列化。


     写缓冲器

    写的时候,发现相应 缓存行的状态是S, 就是共享,说明其他cpu也有副本, 这时候要发 无效 的通知出去广播给其他cpu把缓存里面的值为无效(Invalid)状态 本来是要等回复才能继续的, 有了写缓冲器 就可以先把修改的数据放到写缓冲器,然后通知等其他cpu等他们回复(ack), 这个时候不会造成线程阻塞,cpu可以利用等待的时间继续向下执行,等回复都到了以后cpu再来把数据从写缓冲器搬运到缓存行。
     
    存储转发
    cpu读取数据的时候先从 写缓存器读, 没有 再去 读高速缓存, 这样就可以还是读到真的数据了

    无效化队列

    其他cpu收到无效通知以后, 并不把数据无效化, 而是存入无效化队列 就回复 收到无效Ack,这样可以让对方早点收到回复,等cpu忙完当前的事在进行读取无效化队列。

    这样会造成一些问题

    1. 存储转发:cpu0 更新了a的值, 写到写缓冲器就往下走了,过一阵,要读a,这时先去写缓存器读, 读到的自以为是最新的,但是没准这一阵时间里面, cpu1已经改过a的值了,但是, cpu1发过来的无效通知, 是管不到 cpu0的写缓冲器的。
    2. 写缓冲器:其他CPU还没有给我们回答的时候我们已经执行下一步代码了。
    3. 无效化队列:其他CPU已经给对方应答的时候自己本身还没有去把这个值改为无效状态,这样就造成当前变量已经无效,但是通知还在无效队列化中,会取到旧值。

    存储屏障 加载屏障 

    总之, 写缓冲器 ,无效化队列 就是导致了可见性问题, 明明写了 其他线程看不到这就需要编译器等底层系统 借助 内存屏障

    存储屏障 : 让cpu 将 写缓冲器排空,写入高速缓存 这叫冲刷, 这样其他cpu 就会收到通知, 其他cpu可以来拿新数据
    加载屏障:cpu 根据无效化队列里面的信息,删除其高速缓存的无效数据(就是状态变为I)

    这2个屏障的成对使用, 才能保证更新可见

    原文连接:https://www.jianshu.com/p/8a95094fb344

  • 相关阅读:
    360安全桌面的屏保图片在哪个目录下?
    IntelliJ 注解@Slf4j后找不到log问题解决
    运行springboot项目报错:Field userMapper in XX required a bean of type 'xx' that could not be found.
    springsecurity
    Error creating bean with name 'sqlSessionFactory' defined in class path resource [config/spring/applicationContext.xml]: Invocation of init method failed;
    idea热部署
    数据结构导论 三 线性表-顺序存储
    数据结构导论 二 时空性
    树莓派安装、卸载、更新软件
    数据结构导论第一章
  • 原文地址:https://www.cnblogs.com/blwy-zmh/p/12748566.html
Copyright © 2011-2022 走看看