1

我试图更深入地了解在 C++ 11 中编写多线程应用程序时我有多少选项。

简而言之,到目前为止我看到了这 3 个选项:

  • 具有显式锁定和释放机制的互斥体,它们通过锁定和释放来保持线程同步,这很昂贵并且不能保证我的代码执行的顺序,但通常这种解决方案在不同的内存模型之间是非常可移植的。
  • 原子操作,由于 atomic = 1single operation without a race 并且始终是一致的,sync 是在不加锁和释放的情况下完成的,没有race 就不需要加锁,具有高度优化的原子操作,但是 atomics 仍然不能保证我的代码将执行的顺序。
  • 栅栏,它们在我的代码中创建了一个块,编译器无法重新排序任何内容,灵活性较低,并且它们在代码维护方面往往成本高昂,因为我总是必须关注真正正在执行的内容以及按什么顺序,但它们也改进了缓存技术,在这 3 种解决方案中,它们可能是行为最可预测的一种。

这或多或少是我从关于线程和内存模型的第一堂课中学到的核心,我的问题是:

我打算使用无锁数据结构和原子来实现灵活性和良好的性能,这里的问题是,显然 X86 机器执行的内存重新排序与 ARM 机器不同,我希望尽可能地保持我的代码可移植至少在这两个平台上,那么当两个平台不能保证具有相同的重新排序机制时,你可以建议什么样的方法来编写一个可移植的多线程软件?或者原子操作是最好的选择,因为它现在是我错了?

例如,我注意到英特尔 TBB 库(不是 C++11 代码)正在移植到 ARM/Android,并对专用于原子的部分进行了大量修改,所以也许我可以用 C+ 编写可移植的多线程代码+11,使用无锁数据结构,并在稍后将我的库移植到另一个平台时优化有关原子的部分?

4

2 回答 2

1

围绕多线程编程的问题不是特定于语言或特定于体系结构的。你最好先用一个概括的观点来研究它们——然后作为第二步,将你对特定语言、库、平台等的一般理解专门化。

我上学时需要的课本是:

并发和分布式编程原理 - Ben-Ari

我相信第二版是 2006 年。可能有更好的,但这对于初学者来说应该足够了。

于 2013-06-26T17:45:28.630 回答
1

是的,X86 和 ARM 有不同的内存模型。然而,C++11 内存模型不是特定于平台的,它在任何地方都有相同的行为。

这意味着 C++11 原子的实现在每个平台上都是不同的——在 x86 上,它具有相当强大的内存模型,std::atomic在存储值时可能不需要特殊的汇编指令就可以实现,而在 ARM 上,实现需要特殊内部锁定或围栏指令。

所以你可以简单地使用 C++11 中的原子类,它们在所有平台上的工作方式都是一样的。如果您愿意,如果您完全确定自己在做什么,您甚至可以调整内存顺序。较弱的内存顺序可能会更快,因为原子的实现可能需要更少的汇编程序指令用于内部的锁和栅栏。

我强烈建议您观看 Herb Sutter 的谈话Atomic Weapons以获得有关此的一些详细解释。

于 2013-06-26T21:32:37.473 回答