C11混合原子和非原子访问变量

时间:2017-09-21 22:40:21

标签: c atomic c11

有时您可能希望以原子方式和非原子方式访问变量。这就是为什么我觉得在gcc上你可以写出类似的东西:

int var = 0;
var++;
atomic_fetch_add(&var, 1);

但是这不能用clang 4.0.1编译:

error: address argument to atomic operation must be a pointer to _Atomic type ('int *' invalid)
atomic_fetch_add(&var, 1);

我能找到的最佳解决方案是演员:

int var = 0;
(*(int*)&var)++;
atomic_fetch_add(&var, 1);

是否有更简单便携的方法来实现这一目标?

2 个答案:

答案 0 :(得分:2)

C11中有两个接口允许您对限制较少的原子对象进行操作。

首先,你总是可以覆盖一个原子对象,当你知道你是唯一一个访问它时,通常在初始化阶段,使用atomic_init就可以了。

其次,如果在执行期间即使使用多个线程也需要较少的访问保证,您可以使用限制较少的访问模式。也就是你可以做atomic_fetch_and_add_explicit(&var, 1, memory_order_relaxed)。这仍然保证您的访问权限是不可分割的(您希望从原子中获取的属性之一),但它不能保证另一个线程何时看到更新的值。

但一般来说,如果原子访问对性能至关重要,那么你做错了。因此,在尝试使用原子语言进行语义上难以处理之前,请对代码进行基准测试,看看这是否真的是瓶颈。如果是这样,首先考虑改变算法的方法,例如在不受竞赛影响的局部变量中进​​行更多计算。只有当所有这些都无法提供您想要的性能时,才能了解C11提供的不同内存语义。

答案 1 :(得分:0)

C标准定义的抽象机器具有与大多数真实机器截然不同的存储视图。特别是,不是将内存访问视为可以根据所需环境以各种不同方式执行的操作,而是将每个对象视为支持一种读取,最多一种写入(const - 合格的对象不支持任何类型的写入);访问对象所需的读写类型取决于其类型。

这种方法可能对某些类型的硬件平台或某些优化策略有用,但对于在现实世界平台上运行的多种程序来说非常不合适。不幸的是,标准没有认识到程序员可以指出某些对象大多数时候应该被视为“普通”存储的任何实用方法,但是认识到在程序执行期间某些特定时间它们需要更精确的存储器语义。 / p>