我可以在没有atomic_load的情况下读取原子变量吗?

时间:2017-02-02 13:46:58

标签: c multithreading c11

我有一个单作家,多读者的情况。有一个线程正在写入的计数器,任何线程都可以读取此计数器。由于单个写入线程不必担心与其他线程争用数据访问,以下代码是否安全?

#include <stdatomic.h>
#include <stdint.h>

_Atomic uint32_t counter;

// Only 1 thread calls this function. No other thread is allowed to.
uint32_t increment_counter() {
    atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
    return counter;  // This is the line in question.
}

// Any thread may call this function.
uint32_t load_counter() {
    return atomic_load_explicit(&counter, memory_order_relaxed);
}

作者线程只是直接读取counter而不调用任何atomic_load*函数。这应该是安全的(因为多个线程读取值是安全的),但我不知道声明变量_Atomic是否限制您直接使用该变量,或者如果您需要始终读取它使用其中一个atomic_load*函数。

2 个答案:

答案 0 :(得分:2)

是的,保证您对_Atomic个对象执行的所有操作都会受到影响,就好像您将发出具有顺序一致性的相应调用一样。在您的特定情况下,评估等同于atomic_load

但是在那里使用的算法是错误的,因为通过执行atomic_fetch_add和评估,返回的值可能已经被另一个线程更改。正确的是

uint32_t ret = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
return ret+1;

这看起来有点不理想,因为添加了两次,但是一个好的优化器会对此进行排序。

答案 1 :(得分:0)

如果你重写了这个功能,这个问题就消失了:

uint32_t increment_counter() {
    return 1 + atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
}