【问题标题】:Cache consistency & spawning a thread缓存一致性和生成线程
【发布时间】:2011-02-28 09:27:46
【问题描述】:

背景

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

假设

  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(由于上面未显示的一些“预热代码”。)

问题

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

根据我对处理器缓存的新知识,在 print() 语句时,P2 可能没有收到由 P1 在 main() 中的赋值导致的 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

【问题讨论】:

    标签: multithreading caching thread-safety cpu-architecture


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      我将在这里只对 Java 说话myThread() 保证打印 1,因为 Java 语言规范 中的 happens before definition(第 17.4 节) .5)。

      main() 中对sharedVar 的写入发生在使用函数myThread() 生成线程之前,因为变量赋值在程序顺序中排在第一位。接下来,生成一个线程发生在线程中正在启动的任何操作之前。通过第 17.4.5 节中定义的传递性 (hb(x, y)hb(y, z) 暗示 hb(x, z)),写入变量sharedVar 发生在 print()myThread() 中读取sharedVar

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-03
        • 2010-12-30
        • 2013-05-21
        • 2015-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多