在某个地方我读到一元运算符本质上是原子运算符,因此它们可以在多线程环境中原样使用。为了证实这一点,我写了两个单独的程序,在中
- 我使用了一个变量x,并使用一元运算符++x递增
- 我使用了一个变量x,并使用x=x+1递增
我比较了两个程序的反汇编,没有发现任何差异。请提供您对此的意见。
在某个地方我读到一元运算符本质上是原子运算符,因此它们可以在多线程环境中原样使用。
那个来源完全错误。您需要使用std::atomic
(或等效的C)来实现原子性–一元运算并不特殊。
我比较了两个程序的反汇编,没有发现的差异
这并不意味着生成的操作是原子操作。没有区别,因为任何像样的编译器都会将x=x+1
和++x
优化到同一个程序集中(假设是内置类型)。
在编写跨平台C++时,使用std::atomic<>
时只有原子行为。
的确,在某些平台上,比如英特尔64位,处理器保证inc
是原子的。但是,请不要编写依赖于此的代码!作为您未来的调试器,我想知道哪些数据是要在线程上共享的,哪些不是。
使用std::atomic<int>
可能需要更多的工作来编写,但是,它确实保证了一切都是原子性的(在每个平台上),要么回到平台需求(std::atomic::is_lock_free),要么显式地在访问周围加锁。它还插入了保护程序,以确保其他处理器内核的缓存无效(如果平台需要这样做)。
在英特尔64位的实践中,这应该会给您提供相同的程序集,如果没有,请在编译器上记录错误。
同时,一些使用int的操作可能不是原子操作(运算符*=),std::atomic
根本不包含这些操作,需要正确处理这些操作。
附带说明:++x
和x = x+1
是不同的操作,它们可能被优化为相同的程序集。考虑到非原子平台需求,第二个问题突然出现,需要数天时间才能解决。
一元运算符必然是原子运算符的断言纯属无稽之谈。
例如,++x
需要对x
进行读写,这样就有可能出现数据竞争。
++x
编译为与x = x + 1
相同的代码这一事实并不相关。
如果希望避免数据竞争,则使用原子类型,如果没有合适的原子类型,则使用互斥单元。为避免疑义,int
不一定是原子类型。
在某个地方我读到一元运算符本质上是原子的,因此它们可以在多线程环境中按原样使用。
这是错误的。例如,x++
需要x
的加载、x
的添加和存储。这些指令本质上不是原子指令。
不正确。即使是这样,什么原因会https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases然后呢?
我认为他们的意思可能是,对这样的运算的计算通常是非常微小的,因此很可能永远不会有竞争条件,这在实时代码中最为真实,因为你不会同时在4个循环中计算x++。
您没有指定x的类型。
- 如果x是32位整数,而平台是16或8位,则"x++"运算肯定会进行多次操作
- x甚至可能不是基本类型,x可能是Class的一个实例,其中运算符++所做的事情要比递增整数复杂得多
操作stronglr的原子性取决于目标系统。在像RISC微控制器这样的RMW系统上,一元操作可能不是原子操作。
这个问题没有单一的通用答案。
您对生成的代码进行假设,如果只生成一条指令,是的,它将是原子的,否则不是。
在您的情况下,这假设目标处理器有指令inc <address>
,编译器将生成它
一元运算符的原子行为
在C中,修复前/修复后的++
不是一元运算符,如& * + - ~ !
。而是一元表达式的一部分。因此问题标题与正文不一致。
即使是像+
这样的一元运算符也不是原子运算符,因为对对象的访问(想想long long
)需要读取多个操作代码。