第十一章多线程编程的硬件基础与Java内存模型
高速缓存内部结构示意图
缓存条目的结构
Data Block也被称为缓存行,它是高速缓存与主内存之间的数据交换最小单元,用于存储从主内存中读取或准备写往内存的数据。Tag则包含了与缓存行中数据相应的内存地址的部分信息(内存地址的高位部分比特)。Flag则用于表示响应缓存行的状态信息。
内存地址的解码结果包括tag、index以及offset三部分,index相当于桶号,tag相当于缓存条目的相对编号,offset是缓存行内的位置偏移。
MESI协议中一个缓存条目的Flag值有以下四种可能:Invalid(无效的,记为I)、shared(共享的,记为S),Exclusive(独占的,记为E)和Modified(更改过的,记为M)。
Processor 0读取数据S的实现
Processor 0写数据S的实现
写缓冲器
写缓冲器是处理器内部的一个容量比高速缓存还小的私有高速存储部件。一个处理器无法读取另外一个处理器的写缓冲器中的内容。
内存写操作的执行处理器在将写操作的相关数据写入写缓冲器之后便认为该写操作已经完成,一个处理器接收到其他处理器所回复的针对同一个缓存条目的所有Invalidate Acknowledge消息的时候,该处理器会将写缓冲器中针对相应地址的写操作的结果写入相应的缓冲行中。
无效化队列
引入无效化队列后,处理器在接收到Invalidate消息之后并不会删除消息中指定地址对应的副本数据,而是将消息存入无效化队列之后就回复Invalidate Acknowledge消息,从而减少了写操作执行处理器所需的等待时间。
存储转发
处理器在执行读操作的时候会根据相应的内存地址查询写缓冲器。如果写缓冲器存在相应的条目,那么该条目所代表的写操作的结果数据就会直接作为该读操作的结果返回;否则处理器才从高速缓存中去读取数据。
重排序
写缓冲器可能导致StoreLoad重排序,如一个值的修改值在Processor 1写缓冲器中,那么其他处理器读到的还是Processor 1高速缓存器中的旧值
写缓冲器可能导致StoreStore重排序,同样也是因为新值在写缓冲器中,读取到的是旧值。
无效化队列可能导致LoadLoad重排序,原因是Invalidate消息还在无效化队列中,数据的值未被修改。
可见性
我们必须将写缓冲器中的内容写入其所在的处理器的高速缓存之中,即冲刷缓冲器,这需要内存屏障中的存储屏障;同时我们还需要处理无效化队列,这需要加载屏障。
写线程的执行处理器所执行的存储屏障保障了该线程对共享变量所作的更新对读线程来说是同步的;读线程的执行处理器所执行的加载屏障将写线程对共享变量所作的更新同步到该处理器的高速缓存中。