我可以在没有 atomic_load 的情况下读取原子变量吗?
Can I read an atomic variable without atomic_load?
我有一个单一的作者,多个 reader 的情况。有一个线程正在写入的计数器,任何线程都可以读取该计数器。由于单写线程不用担心与其他线程争用数据访问,下面的代码安全吗?
#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*
函数之一。
是的,您对 _Atomic
对象执行的所有操作都保证像您发出具有顺序一致性的相应调用一样有效。在您的特定情况下,评估相当于 atomic_load
.
但是那里使用的算法是错误的,因为通过执行 atomic_fetch_add
和评估,返回的值可能已经被另一个线程更改。正确的是
uint32_t ret = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
return ret+1;
这看起来有点次优,因为加法进行了两次,但好的优化器会解决这个问题。
如果你重写这个函数,这个问题就消失了:
uint32_t increment_counter() {
return 1 + atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
}
我有一个单一的作者,多个 reader 的情况。有一个线程正在写入的计数器,任何线程都可以读取该计数器。由于单写线程不用担心与其他线程争用数据访问,下面的代码安全吗?
#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*
函数之一。
是的,您对 _Atomic
对象执行的所有操作都保证像您发出具有顺序一致性的相应调用一样有效。在您的特定情况下,评估相当于 atomic_load
.
但是那里使用的算法是错误的,因为通过执行 atomic_fetch_add
和评估,返回的值可能已经被另一个线程更改。正确的是
uint32_t ret = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
return ret+1;
这看起来有点次优,因为加法进行了两次,但好的优化器会解决这个问题。
如果你重写这个函数,这个问题就消失了:
uint32_t increment_counter() {
return 1 + atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
}