首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候应该使用原子操作?

什么时候应该使用原子操作?
EN

Software Engineering用户
提问于 2022-07-29 09:23:11
回答 2查看 988关注 0票数 3

我从来没有使用过原子操作,而且对如何使用原子操作基本上一无所知。然而,在查看Qt的后端:https://doc.qt.io/qt-6/qatomicinteger.html时,我经常会遇到这样的对象

这使我怀疑这里是否有一个我没有适当利用的特性。

因此我的问题是,

  • 什么时候应该使用原子操作?
  • 这是为了提高性能吗?
  • 除了表现之外,还有其他考虑吗?
  • 什么时候才能看到某些人的代码,并对他们进行指责,因为他们没有使用原子操作?

回首过去,我想知道是否有一些地方我应该使用它们,但只是用一个互斥。

EN

回答 2

Software Engineering用户

发布于 2022-07-29 11:42:32

原子操作对于编写具有共享可变状态的安全并发/多线程代码非常有用,而不必求助于(昂贵的)锁或互斥。对于诸如整数或指针之类的小数据类型,atomics允许我们替换类似于

代码语言:javascript
复制
{
  QMutexLocker locker(&mutex);
  x += 1;
}

像原子一样

代码语言:javascript
复制
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 )可能会损坏数据。

对你的问题的具体回答:

  • 什么时候应该使用原子操作?当以下所有内容都有效时:
    • 您有多个线程共享可变状态。
    • 对此状态的修改只影响单个单词(整数、指针、…)。
    • 你想要避免锁/互斥

反指示:

代码语言:javascript
复制
- 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/mutexes
  • 这是为了提高性能吗?主要目的是提高正确性。但是不同的内存顺序允许我们选择最轻松的(因此也是最快的)内存顺序来满足我们的需求。当然,我们总是可以强制执行顺序一致的顺序(memory_order_seq_cst),但这通常是最慢的,并且会涉及CPU级别的锁。
  • 除了表现之外,还有其他考虑吗?正确。
  • 什么时候才能看到某些人的代码,并对他们进行指责,因为他们没有使用原子操作?不用谢。
    • 责难人们通常不是很有教益--这会引起怨恨。
    • 如果有人在线程之间共享可变状态,而不通过互斥、锁或atomics保护访问,则存在潜在的争用条件。提出这个问题可能是有意义的。
    • 如果有人使用互斥或锁来保护单字数据更改,切换到atomics可能会导致简化和性能改进。
票数 7
EN

Software Engineering用户

发布于 2022-07-29 17:35:25

如果你问这个问题,那你就不应该问了。你应该检查你是否有多线程代码,多个线程可以读取或写入相同的变量(至少有一个作者),然后阅读你的语言规则,可能是处理器的规则,在这种情况下,这是否会给你带来问题(可能会导致你很难找到问题),而它们可以通过使用互斥、原子访问、串行队列,或者通过向知道如何解决这些问题的人寻求帮助来解决这些问题。

但是原则是:如果使用变量的所有线程总是使用原子操作,而一些线程使用原子操作修改变量,那么任何其他线程都会看到修改尚未开始,或者已经完成。它从来没有看到变量之间的状态。

票数 -3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/440093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档