接着上次的问题------并不意味着最终的结果是"2"。
为什么?因为涉及到高速缓存与内存总线的工作细节。处理器可能有高速缓存,用来保存最近从主存中读出数据的拷贝的快速本地内存。在一个"回写"(write-back)高速缓存系统中,数据最初只是保存在高速缓存中,而在后面的时间写入(刷新)主存。在不保证写顺序的系统中,高速缓存中的数据块可能在任何处理器认为方便的时候写入主存。如果两个处理器向同一内存地址写不同的数据,则不同的数据将分别保存在二者的高速缓存中。最终两个值将写到主存中,但是是在随机的时刻写入,与写到相应的高速缓存中的顺序无关。
即使同一线程(或处理器)中的两个写操作也不需要在内存中表现相同的顺序。内存控制器可能发现以相反的顺序写入会更快或更方便。

问题还不仅局限于两个线程写内存。想像一下,一个线程在某个处理器上向内存中写入数据,而另一个线程在其他处理器上读相同的内存。好像很显然地,线程将得到最近写入的值,而在有些硬件上的确如此。这种现象有时被称为"内存一致性"或"读写排序"。但是在处理器之间确保这种同步是复杂的,它会降低内存系统的速度,并且对大部分代码没有任何意义。现在很多的计算机(通常是最快的计算机)不再保证不同处理器间内存访问的顺序,除非程序使用特殊的指令,这些指令就是常说的"内存屏障"(memory barrier)。
内存屏障确保:所有在内存屏障之前发起的内存访问,必须先于在设置屏障之后发起的内存访问之前完成。
内存屏障是一堵移动的墙,而不是刷新cache的命令。
即使没有读写排序和内存屏障,写内存好像也必须是原子性的操作。即任何其他线程只能看到完整的旧数据或者看到完整的新数据。但这也并不总是正确的。大部分计算机有一个天然的内存粒度,依赖于内存的组织和总线结构。即使处理器读写8位数据,内存传输可能以32位或64位为单位。这意味着,相对于其他覆盖相同32或64位数据单元的内存操作而言,8位写操作不是原子操作。大部分计算机会写包含修改数据的整个内存数据单元(如32位)。如果两个线程向同一个32位内存单元中写入不同的8位数据,则结果是最后写入的线程将确定两个8位字节的值,即覆盖第一个线程写入的值。图3.8显示了这种效果。

聪明的你是不是想到了一种情况------如果一个变量跨越了内存单元的界限(这将在允许对齐内存访问的机器上出现),计算机不得不在两次总线事物中传送数据。例如,一个非对齐的32位数据可能需要写两个相邻的32位内存单元。如果其中一个内存单元同时被另一个处理器写入,则将丢失一半数据。这被称为"word tearing",如图3.9所示。

欢迎关注,持续前进。
