int b = 1000;
b -= 20;
以上内容中是否有原子操作?在C语言中,什么是原子操作?
这取决于具体的实现。按照标准,在C语言中没有任何一个操作是原子性的。如果您需要原子操作,可以查看您编译器的内置函数。
sig_atomic_t
了! - Jens这取决于架构/实现。
如果您想要原子操作,我认为C99通过sig_atomic_t
类型进行了标准化,但不确定。
来自GNU LibC文档:
实际上,您可以假设int和其他不超过int的整数类型是原子的。 您还可以假定指针类型是原子的; 这非常方便。 所有GNU C库支持的机器和我们所知道的所有POSIX系统上都是如此。
b -= 20
是线程安全的吧? - David Heffernanint b = 1000
。 - Vinicius Kamakurasig_atomic_t
一样,因此您可以同时获得两者,但是除了不是Unix之外,GNU还不是C。 - Steve Jessopsig_atomic_t
,但不使用原子 CPU 指令,并且(假设 C 实现具有线程)在访问期间不禁用多线程。这很不可能,而且可能效率极低,但是合法的,因此展示了关于信号与线程的原子 wrt 定义的差异。 - Steve Jessopint b=1000;
b-=20;
第一行代码应该是一个原子操作。如果CPU的指令集中包含直接从内存中减去的指令,则第二个代码行可以是原子操作。我认为这样做的原因是,第一行代码很可能只需要一个汇编(机器)指令。指令要么执行要么不执行。我认为任何机器指令都不能在中途被打断。
在同一个链接中,它说:“如果线程A将32位值作为原子操作写入内存,线程B将永远无法读取内存位置并仅查看写出的前16位。” 看起来任何单个机器指令都不能在中途被打断,因此在线程之间自动成为原子操作。
在C语言中,增加和减少一个数字不是原子操作。某些架构支持原子增加和减少指令,但不能保证编译器会使用它们。你可以看看Qt的引用计数作为例子。它使用原子引用计数,在某些平台上,它是通过特定于平台的汇编代码实现的,而在其他平台上,则使用互斥锁来锁定计数器。
如果您在代码的性能关键部分没有进行增加或减少操作,那么您只需在执行此操作时使用互斥锁即可。如果您在代码的性能关键部分使用它,您可能需要尝试以不使用共享内存的方式重写代码,以便从多个位置访问此操作,或者使用具有更高粒度的互斥锁,以便它们不会影响性能,或者使用汇编来确保操作是原子的。
引用自ISO C89,7.7信号处理<signal.h>
定义的类型是
sig_atomic_t
,它是一个整数类型的对象,可以作为原子实体访问,即使存在异步中断也是如此。
sig_atomic_t
自C89(!)以来就存在了。 - Jenssig_atomic_t
是存在的,但它如何允许您以原子方式对变量执行算术运算?我认为这个问题涉及线程而不是信号处理程序。 - David Heffernan=
和 C++:https://dev59.com/eGsy5IYBdhLWcg3w0RbT - Ciro Santilli OurBigBook.com