一元增量运算符的原子行为
Atomic behavior of unary increment operators
我在某处读到一元运算符本质上是原子的,因此它们可以在多线程环境中按原样使用。为了确认这一点,我在
中编写了两个单独的程序
- 我使用变量 x 并使用一元运算符 ++x 递增
- 我使用变量 x 并使用 x=x+1 递增
我比较了两个程序的反汇编,没有发现区别。请提供您对此的意见。
Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment.
那个来源是完全错误的。您需要使用 std::atomic
(或等效的 C 语言)来实现原子性——一元运算并不特殊。
I compared the disassembly of both programs and found no difference
这并不意味着生成的操作是原子的。没有区别,因为任何体面的编译器都会将 x=x+1
和 ++x
优化到同一个程序集中(假设内置类型)。
一元运算符必然是原子的断言是一个神话。
例如,++x
需要对 x
进行读写操作,这样就有可能出现数据竞争。
++x
编译为与 x = x + 1
相同的代码这一事实无关紧要。
如果您想避免数据竞争,则使用原子类型,或者如果没有合适的原子类型可用则使用互斥单元。为免生疑问,int
不一定是原子类型。
Somewhere I read that unary operators are atomic by nature and so they
can be used as it is in multi threaded environment.
这是错误的。例如,x++
需要 x
的加载、x
的添加和存储。这些指令本质上不是原子的。
不正确。就算是,那https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases又有什么理由呢?
我认为他们的意思可能是,对此类操作的计算通常非常微小,因此很可能永远不会出现竞争条件,这在实时代码中大多是正确的,您不会同时在 4 个 for 循环中计算 x++ .
stronglr 操作的原子性取决于目标系统。在 RISC 微控制器等 RMW 系统上,一元操作可能不是原子的。
这个问题没有单一的通用答案。
编写跨平台 C++ 时,使用 std::atomic<>
时只有原子行为。
确实在某些平台上,例如 Intel 64 位,处理器保证 inc
是原子的。但是,请不要编写依赖于此的代码!作为您未来的调试器,我想知道哪些数据旨在通过线程共享,哪些不是。
使用 std::atomic<int>
可能需要多写一些工作,但是,它确实通过回退到平台要求 (std::atomic::is_lock_free) 来保证一切都以原子方式运行(在每个平台上),或者通过显式锁定访问权限。它还插入保护以确保其他处理器内核的缓存无效(如果平台需要)。
在 Intel 64 位的实践中,这应该会为您提供相同的程序集,如果不是,请在您的编译器上记录一个错误。
同时,一些 int 操作可能不是原子操作(运算符*=),std::atomic
根本不包含这些操作,需要您正确地使用它们。
旁注:++x
和 x = x+1
是不同的操作,它们可能针对同一程序集进行了优化。鉴于非原子平台要求,第二个突然是一个需要几天才能解决的错误。
你对生成的代码做一个假设,如果只生成一条指令是,它将是原子的,否则不是。
在您的情况下,这假设目标处理器具有指令 inc <address>
并且编译器将生成它。
您没有指定 x 的类型。
- 如果平台为16位或8位时x为32位整数,'x++'操作
一定会进行多次操作
- x 甚至可能不是基本类型,x 可能是 Class 的实例,其中 operator++ 做的事情要复杂得多,然后只需递增 integer
Atomic behavior of unary operators
在C中,pre/post修复++
不是unary-operators如& * + - ~ !
。但是 unary-expression 的一部分。所以问题标题与body.
不一致
即使像 +
这样的一元运算符也不是原子的,因为访问 object(认为 long long
)会读取多个操作代码。
我在某处读到一元运算符本质上是原子的,因此它们可以在多线程环境中按原样使用。为了确认这一点,我在
中编写了两个单独的程序- 我使用变量 x 并使用一元运算符 ++x 递增
- 我使用变量 x 并使用 x=x+1 递增
我比较了两个程序的反汇编,没有发现区别。请提供您对此的意见。
Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment.
那个来源是完全错误的。您需要使用 std::atomic
(或等效的 C 语言)来实现原子性——一元运算并不特殊。
I compared the disassembly of both programs and found no difference
这并不意味着生成的操作是原子的。没有区别,因为任何体面的编译器都会将 x=x+1
和 ++x
优化到同一个程序集中(假设内置类型)。
一元运算符必然是原子的断言是一个神话。
例如,++x
需要对 x
进行读写操作,这样就有可能出现数据竞争。
++x
编译为与 x = x + 1
相同的代码这一事实无关紧要。
如果您想避免数据竞争,则使用原子类型,或者如果没有合适的原子类型可用则使用互斥单元。为免生疑问,int
不一定是原子类型。
Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment.
这是错误的。例如,x++
需要 x
的加载、x
的添加和存储。这些指令本质上不是原子的。
不正确。就算是,那https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases又有什么理由呢?
我认为他们的意思可能是,对此类操作的计算通常非常微小,因此很可能永远不会出现竞争条件,这在实时代码中大多是正确的,您不会同时在 4 个 for 循环中计算 x++ .
stronglr 操作的原子性取决于目标系统。在 RISC 微控制器等 RMW 系统上,一元操作可能不是原子的。
这个问题没有单一的通用答案。
编写跨平台 C++ 时,使用 std::atomic<>
时只有原子行为。
确实在某些平台上,例如 Intel 64 位,处理器保证 inc
是原子的。但是,请不要编写依赖于此的代码!作为您未来的调试器,我想知道哪些数据旨在通过线程共享,哪些不是。
使用 std::atomic<int>
可能需要多写一些工作,但是,它确实通过回退到平台要求 (std::atomic::is_lock_free) 来保证一切都以原子方式运行(在每个平台上),或者通过显式锁定访问权限。它还插入保护以确保其他处理器内核的缓存无效(如果平台需要)。
在 Intel 64 位的实践中,这应该会为您提供相同的程序集,如果不是,请在您的编译器上记录一个错误。
同时,一些 int 操作可能不是原子操作(运算符*=),std::atomic
根本不包含这些操作,需要您正确地使用它们。
旁注:++x
和 x = x+1
是不同的操作,它们可能针对同一程序集进行了优化。鉴于非原子平台要求,第二个突然是一个需要几天才能解决的错误。
你对生成的代码做一个假设,如果只生成一条指令是,它将是原子的,否则不是。
在您的情况下,这假设目标处理器具有指令 inc <address>
并且编译器将生成它。
您没有指定 x 的类型。
- 如果平台为16位或8位时x为32位整数,'x++'操作 一定会进行多次操作
- x 甚至可能不是基本类型,x 可能是 Class 的实例,其中 operator++ 做的事情要复杂得多,然后只需递增 integer
Atomic behavior of unary operators
在C中,pre/post修复++
不是unary-operators如& * + - ~ !
。但是 unary-expression 的一部分。所以问题标题与body.
即使像 +
这样的一元运算符也不是原子的,因为访问 object(认为 long long
)会读取多个操作代码。