看了这篇文章中http://images.cnblogs.com/cnblogs_com/1-2-3/thread-synchronization/7.png
的情况 源码在这里class Program
{
    static int n = 0;
    static void foo1()
    {
        for (int i = 0; i < 1000000000; i++) // 10 亿
        {                n = n + 1;
        }
        Console.WriteLine("foo1() complete n = {0}", n);
    }
    static void foo2()
    {
        for (int j = 0; j < 1000000000; j++) // 10 亿
        {                n = n + 1;
        }
        Console.WriteLine("foo2() complete n = {0}", n);
    }
    static void Main(string[] args)
    {
        new Thread(foo1).Start();
        new Thread(foo2).Start();
    }
}
作者说 n在两个CPU的cache中都分别在加一,所以 进行了3个循环后 很可能 两边的cache里面 n都是3我自己加了代码,发现他说的情况是有的。但是按照intel的MESI缓存一致性协议的话 这种情况不应该发生啊:M: 被修改的。处于这一状态的数据只在本CPU中有缓存,且其数据已被修改,没有更新到内存中 
E: 独占的。处于这一状态的数据只在本CPU中有缓存,且其数据没有被修改,与内存一致 
S: 共享的。处于这一状态的数据在多个CPU中有缓存 
I: 无效的。本CPU中的这份缓存已经无效了。 当CPU要读取数据时,只要缓存的状态不是I都可以从缓存中读,否则就要从主存中读。这一读操作可能会被某个处于M或E状态的CPU截获,该CPU将修改的数据写出到内存,并将自己设为S状态后这一读操作才继续进行。只有缓存状态是E或M时,CPU才可以修改其中的数据,修改后缓存即处于M状态。如果CPU要修改数据时发现其缓存不处于E或M状态,则需要发出特殊的RFO指令(Read For Ownership),将其它CPU的缓存设为I状态。 
到底为什么这个缓存一致性协议 形同虚设呢?

解决方案 »

  1.   

    这个和CPU Cache没有关系,你既然学习过intel的cpu cache知识那就应该明白cpu是怎么进行加法计算的,如果还不明白就仔细看下cpu在进行加法计算的时候是怎么运作的。
      

  2.   

    I like this question:) 我来补充一下1楼说的:这个和CPU Cache没有关系,就算不用Cache,这个程序一样会出问题。一致性协议是使得多个CPU issue出来的load/store操作能够以一个约定的“序”对内存可见,Cache一致性协议是在Cache存在的情况下对这个“序”的一个约定和实现。常见的MESI协议简单说就是按照load/store出现在总线上的“序”对内存可见的。(好久没看书了,不保证说的准确)。但是,load/store issue到总线的次序就不归一致性协议管了。这个例子中n=n+1在RISC机器一般会生成:ld n, reg
    add reg, 1
    st reg, n由于这三条指令并没有被锁保护,所以他们的执行并不是原子的,而是可以interleave的。这才是造成问题的根本原因。
      

  3.   

    操作系统的书吧。还有就是Intel相关开发的书。比如多核程序设计之类
      

  4.   

    如果你知道MESI,应该知道看什么书啊。http://product.dangdang.com/product.aspx?product_id=693715
    这本不错,现在可能不好买了。或者搜论文看,memory consistency有一篇综述。不过除非你需要设计一个线程模型,否则基本用不着。