Sma*_*acL 8 c++ multithreading atomic
如果我在多个线程中访问单个整数类型(例如long,int,bool等等),我是否需要使用同步机制(如互斥锁)来锁定它们.我的理解是,作为原子类型,我不需要锁定对单个线程的访问,但我看到很多代码确实使用了锁定.对这些代码进行概要分析表明使用锁具有显着的性能损失,所以我宁愿不这样做.因此,如果我访问的项目对应于总线宽度整数(例如32位处理器上的4个字节),我是否需要在跨多个线程使用时锁定对它的访问?换句话说,如果线程A在线程B从同一个变量读取的同时写入整数变量X,是否有可能线程B最终将前一个值的几个字节与写入的值的几个字节混合在一起?这种体系结构是否依赖,例如32位系统上的4字节整数是否可以,但64位系统上的8字节整数是不安全的?
编辑:刚看到这个相关的帖子,这有点帮助.
您永远不会锁定值 - 您将操作锁定在某个值上.
C&C++没有明确提到线程或原子操作 - 所以看起来它们可能或应该是原子的操作 - 不能保证语言规范是原子的.
它肯定是一个非常不正常的编译器管理int上的非原子读取:如果你有一个读取值的操作 - 可能没有必要保护它.但是,如果它跨越机器字边界,它可能是非原子的.
操作非常简单,m_counter++包括获取,增量和存储操作 - 竞争条件:另一个线程可以在获取之后但在存储之前更改值 - 因此需要通过互斥锁保护 - 或者查找编译器对互锁操作的支持.MSVC具有像_InterlockedIncrement()这样的函数,只要所有其他写操作类似地使用互锁apis来更新内存位置,它就会安全地增加内存位置 - 这比调用一个临界区更轻量级.
GCC具有内部函数__sync_add_and_fetch,也可用于对机器字值执行互锁操作.
在 99.99% 的情况下,您必须锁定,即使它是对看似原子变量的访问。由于 C++ 编译器不知道语言级别上的多线程,因此它可以执行大量重要的重新排序。
举个例子:我被自旋锁实现所困扰,其中解锁只是将零分配给volatile整数变量。编译器在锁定下的实际操作之前对解锁操作进行了重新排序,毫不奇怪,导致了神秘的崩溃。
看:
如果您在一台具有多个内核的机器上,即使写入整数是原子的,您也需要正确地做事情。问题有两方面:
如果这只是第一件事,您可以标记变量volatile,但第二件事才是真正的杀手,您只会在多核机器上真正看到差异。这恰好是一种比以前更普遍的架构......哎呀!是时候停止草率了;为您的平台使用正确的互斥(或同步或其他)代码,以及如何使内存像您认为的那样工作的所有细节都会消失。
| 归档时间: |
|
| 查看次数: |
5466 次 |
| 最近记录: |