我从来没有使用过原子操作,而且对如何使用原子操作基本上一无所知。然而,在查看Qt的后端:https://doc.qt.io/qt-6/qatomicinteger.html时,我经常会遇到这样的对象
这使我怀疑这里是否有一个我没有适当利用的特性。
因此我的问题是,
回首过去,我想知道是否有一些地方我应该使用它们,但只是用一个互斥。
发布于 2022-07-29 11:42:32
原子操作对于编写具有共享可变状态的安全并发/多线程代码非常有用,而不必求助于(昂贵的)锁或互斥。对于诸如整数或指针之类的小数据类型,atomics允许我们替换类似于
{
QMutexLocker locker(&mutex);
x += 1;
}像原子一样
atomicX.fetchAndAddAcquire(1);或者使用C++标准库,我们可以替换
{ std::lock_guard<std::mutex> guard(mutex); x += 1; }
使用
atomicX.fetch_add(1, std::memory_order_acq_rel)。
这具有潜在的性能优势,因为CPU为原子操作提供了专门的指令。此外,还有不同的“内存顺序”,对于哪个值对不同的CPU内核可见,有不同的保证。Atomics允许我们在这里选择适当程度的控制,与使用更严格的排序或互斥/锁相比,更宽松的命令可能带来更好的性能。内存顺序是在C++标准中定义的,例如,参见cppreference.com综述。
特别是在x86体系结构上,您可能不会看到普通易失性变量与使用轻松或获取/发布命令的atomics之间的区别。CPU架构已经为所有内存访问提供了强有力的保证。然而,准确地使用内存顺序在ARM体系结构上是非常重要的。使用过于宽松的内存顺序(或者根本不使用atomics )可能会损坏数据。
对你的问题的具体回答:
反指示:
- the data is only used by a single thread → use ordinary variables
- the shared data remains constant → use ordinary variables
- changes to the shared data affect more than one word at a time → use locks/mutexes
- you do not want to learn about memory orderings → use atomics with sequentially consistent ordering or locks/mutexesmemory_order_seq_cst),但这通常是最慢的,并且会涉及CPU级别的锁。发布于 2022-07-29 17:35:25
如果你问这个问题,那你就不应该问了。你应该检查你是否有多线程代码,多个线程可以读取或写入相同的变量(至少有一个作者),然后阅读你的语言规则,可能是处理器的规则,在这种情况下,这是否会给你带来问题(可能会导致你很难找到问题),而它们可以通过使用互斥、原子访问、串行队列,或者通过向知道如何解决这些问题的人寻求帮助来解决这些问题。
但是原则是:如果使用变量的所有线程总是使用原子操作,而一些线程使用原子操作修改变量,那么任何其他线程都会看到修改尚未开始,或者已经完成。它从来没有看到变量之间的状态。
https://softwareengineering.stackexchange.com/questions/440093
复制相似问题