开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
volatile是如何来保证可见性的呢? 示例代码如下:
instance = new Singleton(); // instance是volatile变量
把这行代码转变成汇编代码,如下:
0x01a3de1d: movb $0×0,0×1104800(%esi);
0x01a3de24: lock addl $0×0,(%esp);
有volatile变量修饰的共享变量进行写操作的时候会多出第二行汇编代码,通过查IA-32架构软件开发者手册可知,Lock前缀的指令在多核处理器下会引发了两件事情:
1)将当前处理器缓存行的数据写回到系统内存(主存。声言Lock信号。)。
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。
1.将当前处理器缓存行的数据写回到系统内存
lock指令是指在指令执行期间,声言处理器的LOCK#信号。在多处理器环境下,主存只有当前处理器一个人可以访问,锁总线。但是随着计算机的发展,LOCK#信号一般不锁总线,而是锁缓存,因为锁总线开销的比较大,其他处理器在总线传输需要等待,所以不利于计算机的运行。在老的处理器中会在总线声言LOCK#信号;在新的处理器中因为访问的内存区域已经缓存在了处理器内部,所以不会声言LOCK#信号,它会锁定内存区域的缓存写回到主内存,其中使用了MESI协议(缓存一致性协议)来确保修改的原子性。缓存一致性协议同一时间只能修改一个处理器的缓存区域。
总线锁定声言lock信号的,为了提高性能,高级的处理器走的是缓存锁定,改哪里锁定哪里,所以不需要声言lock信号。
2.这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效
这个是指MESI协议(修改、独占、共享、无效)中,修改了处理器缓存会使其他处理器中的缓存和主存变为无效。详情看上一章节介绍的MESI协议。
同时处理器会使用嗅探技术去查看其他处理器的缓存和系统内存。这表明处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致。