缓存一致性&产生一个线程

时间:2010-06-06 14:15:43

标签: multithreading caching thread-safety cpu-architecture

背景

我一直在阅读各种书籍和文章,以了解并发执行环境中的处理器缓存,缓存一致性和内存障碍。到目前为止,我一直无法确定我的常见编码实践是否在最严格的意义上是安全的。

假设

  1. 以下伪代码在双处理器机器上执行:

    int sharedVar = 0;
    
    myThread()
    {
        print(sharedVar);
    }
    
    main()
    {
        sharedVar = 1;
        spawnThread(myThread);
        sleep(-1);
    }
    
  2. main()在处理器1(P1)上执行,而myThread()在P2上执行。

  3. 最初,sharedVar存在于P1和P2的缓存中,初始值为0(由于某些“预热代码”未在上面显示。)

  4. 问题

    严格来说 - 最好不要假设任何特定类型的CPU - myThread()保证打印1?

    凭借我对处理器缓存的新发现,似乎完全有可能在print()语句时,P2可能没有收到由main()中的P1赋值引起的sharedVar的失效请求。因此,myThread()似乎可以打印0。

    参考

    这些是我一直在阅读的相关文章和书籍:

    1. Shared Memory Consistency Models: A Tutorial
    2. Memory Barriers: a Hardware View for Software Hackers
    3. Linux Kernel Memory Barriers
    4. Computer Architecture: A Quantitative Approach

2 个答案:

答案 0 :(得分:1)

  

严格来说 - 最好不要假设任何特定类型的CPU - myThread()保证打印1?

从理论上讲,它可以打印01,即使在x86上,也可以打印stores can move after loads on almost any architecture

在实践中,很难让myThread()打印0 产生一个线程很可能会起到隐式存储/释放memory barrier的作用,因为它可能会: - 在执行路径上至少有一条指令导致内存屏障 - 互锁指令,显式内存屏障指令等,
- 或者在调用myThread()时,商店只会从store buffer退出/消失,因为设置新线程会导致执行许多指令 - 其中包括许多商店。

答案 1 :(得分:0)

我只会在这里说 myThread()保证打印1,因为来自 Java语言规范的happens before definition (第17.4.5节)。

sharedVar 中对main()的写入发生在生成具有函数myThread()的线程之前,因为变量赋值首先出现在程序顺序。接下来,在正在启动的线程中的任何操作之前发生线程。通过第17.4.5节中的定义的传递性( hb(x,y) hb(y,z)暗示 hb(x,z)< / em>),写入变量sharedVar 发生在 print()读取sharedVar中的myThread()之前。

您可能也喜欢阅读Brian Goetz关于此主题的文章Java theory and practice: Fixing the Java Memory Model, Part 2,以及他的书Java Concurrency in Practice