目前的 cpu 架构中,主要通过在 volatile 修饰的变量进行读写时加入屏障来实现可见性。
invalidQueue、storeBuffer 与可见性
底层上 cpu 主要通过 mesi 协议来实现多核 cpu 之间的缓存一致性(具体可查询相关内容),而 mesi 中为了实现 cpu 的高效处理,引入了 invalidQueue 以及 storeBuffer 两种数据结构。首先,在 cpu 中只有多核 cpu(cpu0,cpu1)都占有的变量(共享变量)才会存在不可见问题,假设 cpu0 和 cpu1 都在其高速缓冲中占有了变量 x,而 cpu0 在某一时刻开始修改 x,这时候 cpu0 会通知 cpu1 将其对应的缓存行置为失效状态。具体来说,这时候为了高效处理,cpu0 将修改值存入 storebuffer 中,同时开始通知 cpu1,而 cpu1 则将对应的失效消息放入 invalidQueue 中,然后告知 cpu0 处理完成,cpu0 得到响应后会将对应的修改值从 storebuffer 中刷入高速缓冲中。以上就是 mesi 协议保证多核 cpu 缓存一致性的部分内容。这时候我们可以发现其实是存在问题的,因为 cpu0 没有将修改值刷入主存,而 cpu1 也没有执行对应的失效操作(如果没有执行失效操作,那么 cpu1 仍然取得是高速缓冲中的值,只有失效以后才从主存中获取对应的值)。因此,volatile 修饰符就是在 cpu0 将修改值刷入高速缓存的时候同时刷入主存,而 cpu1 读取 x 的时候将 invalidQueue 中的消息全部执行完毕,从而保证多核 cpu 之间的可见性。