简体   繁体   English

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

[英]C11 mixing atomic and non-atomic access to variable

Sometimes you may want to access a variable both atomically and non-atomically. 有时,您可能想同时访问原子和非原子变量。 Which is why I find convinient that on gcc you can write something like : 这就是为什么我认为在gcc上可以编写类似以下内容的原因:

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

However this does not compile with clang 4.0.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);

The best solution I could find is a cast : 我能找到的最佳解决方案是强制转换:

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

Is there a simpler and portable way to achieve this ? 有没有更简单,更便携的方法来实现这一目标?

There are two interfaces in C11 that allow you to act on an atomic object which are less restrictive. C11中有两个接口,可让您对限制较小的原子对象进行操作。

First, you can always overwrite an atomic object, when you know that you are the only one accessing it, usually during an initialization phase, use atomic_init for that. 首先,您总是可以覆盖一个原子对象,当您知道自己是唯一访问它的对象时,通常在初始化阶段,就可以使用atomic_init

Second, if you need less guarantees for an access during the execution even with several threads, you can use a less restrictive access mode. 其次,如果即使在执行多个线程时也需要较少的访问保证,则可以使用限制较少的访问模式。 Namely you could eg do atomic_fetch_and_add_explicit(&var, 1, memory_order_relaxed) . 即,您可以例如执行atomic_fetch_and_add_explicit(&var, 1, memory_order_relaxed) This still guarantees that your access is indivisible (one of the properties that you want from an atomic) but it doesn't guarantee when another thread sees the updated value. 这仍然保证您的访问是不可分割的 (您希望从原子获得的属性之一),但是不能保证另一个线程何时看到更新的值。

But generally speaking, if atomic accesses are performance critical, you are doing something wrong. 但是通常来说,如果原子访问对性能至关重要,那么您在做错什么。 So before you try semantically difficult dealings with atomics, benchmark your code and see if this really is a bottleneck. 因此,在尝试对原子进行语义上困难的处理之前,请对代码进行基准测试,看看这是否确实是瓶颈。 If so, think first of a way to change your algorithm, eg by doing more computations in local variables that are not subject to races. 如果是这样,请首先考虑一种更改算法的方法,例如,对不受种族限制的局部变量进行更多的计算。 Only if all of that fails to give you the performance you want, have a look into the different memory semantics that C11 offers. 只有当所有这些都不能给您所需的性能时,才可以查看C11提供的不同内存语义。

The abstract machine defined by the C Standard has a rather different view of storage than most real machines. 与大多数实际计算机相比,C标准定义的抽象计算机具有完全不同的存储视图。 In particular, rather than thinking of memory accesses as actions which can be performed in a variety of different way depending upon required circumstances, it instead views each object has supporting one kind of read and at most one kind of write ( const -qualified objects don't support any kind of write); 特别是,与其将存储器访问视为可以根据所需环境以各种不同方式执行的动作,不如将每个对象都支持一种读和一种写( const限定对象不支持)。不支持任何形式的写操作); the kind of read and write required to access an object depend upon its type. 访问对象所需的读写类型取决于对象的类型。

Such an approach may be useful for some kinds of hardware platforms, or for some optimization strategies, but is grossly unsuitable for many kinds of programs running on real-world platforms. 这种方法可能对某些类型的硬件平台或某些优化策略很有用,但根本不适合在实际平台上运行的许多程序。 Unfortunately, the Standard doesn't recognize any practical way by which programmers can indicate that certain objects should be treated as "ordinary" storage most of the time, but recognize that they require more precise memory semantics at certain specific times during program execution. 不幸的是,该标准并没有识别出程序员可以在大多数时间将某些对象视为“普通”存储的任何实用方式,但是认识到它们在程序执行期间的某些特定时间需要更精确的存储器语义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM