C 中的线程和线程安全

Threading and Thread Safety in C

当有一组通用的全局数据需要在多个线程进程之间共享时,我通常使用线程令牌来保护共享资源:

编辑 - 7/22/15(合并 atomics 作为一个可行的选择,根据 Jens 的评论)

我的[第一个]问题是,在C中,如果我以保证每个线程访问的方式编写例程一个且只有一个数组元素:

是否有任何理由认为异步和同时访问相同未保护数组的不同索引(如图所示)会有问题吗?

第二个问题:鉴于一个对象可以被访问为 一个原子实体,即使存在异步中断 ( C99 - 7.14 Signal handling ) would using atomics 也是线程保护的有效方法一个不受保护的变量?

编辑(澄清评论中的问题):
- 此应用程序的具体信息:
- 目标 OS:Windows 7/8/10
- 编译器:C99 兼容(不能使用 C11,其中包括 _Atomic() type specifier
- H/W:英特尔 i7 系列

如果每个线程正在访问不同的数组元素,并且只有它是 "assigned" 的元素,这应该不是问题。以上两种情况本质上是等价的,因为每个数组元素都有自己的地址。

在 C 中,这将取决于您的平台,即编译器、处理器架构和操作系统的组合。

您的编译器可以选择如何使用 cpu 的内部寄存器和指令来使可执行文件看起来执行程序的意图。而C可能对线程一无所知。提供线程库通常是操作系统的工作。

可能有处理器可以通过读取比一个元素大得多的内存块来执行对数组元素的写入,然后只覆盖在内部寄存器中形成一个元素的正确位,然后写入整个补丁回来。单线程程序可以正常工作,但两个或多个线程相互中断可能会导致数组混乱。

另一方面,它可能会很好。

而且如前所述,只读访问总是没问题的。

还有,google是你的朋友。它发现了这个 Whosebug question.

这个(看起来像某种 C 标准) http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 说:

NOTE 1 Two threads of execution can update and access separate memory locations without interfering with each other

NOTE 13 Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this standard, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race. This includes implementations of data member assignment that overwrite adjacent members in separate memory locations. We also generally preclude reordering of atomic loads in cases in which the atomics in question may alias, since this may violate the "visible sequence" rules.

按照我的理解,这将排除 quamrana 的顾虑,并向您保证,如果没有数据竞争,对单独内存位置的不受保护的写入永远不会导致未定义的行为。