i++是原子操作吗

什么是原子操作?

所谓原子操作,就是"不可中断的一个或一系列操作" 。在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能开销昂贵的锁。

那么,GNU C中x++是原子操作吗?请看下面一段代码:

  1. #include <stdlib.h>  
  2. #include <pthread.h>  
  3. static int x;  
  4. void inc()  
  5. {  
  6.     x++;  
  7. }  
  8. void foo(void)  
  9. {  
  10.     int i;  
  11.     for (i = 0; i < 5; i++)  
  12.     {  
  13.         inc();  
  14.     }  
  15. }  
  16. int main(int argc, char *argv[])  
  17. {  
  18.     pthread_t p1, p2;  
  19.     pthread_create(&p1, NULL, (void *)foo, NULL);  
  20.     pthread_create(&p2, NULL, (void *)foo, NULL);  
  21.     pthread_join(p1, NULL);  
  22.     pthread_join(p2, NULL);  
  23.     printf("%d/n", x);  
  24. }  
 

代码输出的x值是多少呢? 

在多线程编程环境中,对全局变量的访问是需要进行同步保护的,当然也可以借用原子操作,这样程序运行结果才是确定的。所以现在的问题是x++是原子操作吗?如果是,则上述代码运行结果x=10。如果不是,则运行结果是不确定的,x值为 [5, 10]范围中的某个值。x++应该是非原子操作,但我又不是很确定,所以只好看汇编代码了。

inc:
        pushl   %ebp
        movl    %esp, %ebp
        movl    x, %eax
        addl    $1, %eax
        movl    %eax, x
        popl    %ebp
        ret

 

从上面的汇编代码片段,显然可以确定x++是非原子的,它由3条汇编指令组成。因此上面的x的值也就是不确定的了,它的最大值可能为10,最小值可能为5。这两种情况分别发生在完全没有同步(即串行)和完全竞争(即每次均同时读取同样的x值)的情况下,两个极端情形,要得到这样的结果,估计要看RP(开个玩笑,呵呵)。 

结论,GNU C中x++不是原子操作,所以特别提供了原子值类型atomic_t。

 

在C语言中,i++操作符本身是不具备线程安全性的。当多个线程同时对同一个变量进行i++操作时,可能会出现竞态条件(Race Condition)的问题。 竞态条件是指多个线程对共享资源的访问产生冲突,导致程序执行结果与期望不符。在i++操作中,实际上包含了读取变量i的值、对其进行加1操作、将结果写回变量i这三个步骤。如果多个线程同时执行这些步骤,就可能导致结果不确定或错误。 为了保证线程安全,可以采取以下措施之一: 1. 使用互斥锁(Mutex Lock):在每个线程访问i++操作之前,首先获取一个互斥锁,确保只有一个线程能够执行i++操作,其他线程需要等待锁的释放。这样可以避免竞态条件的发生。 2. 使用原子操作(Atomic Operation):一些编程语言和库提供了原子操作的支持,这些操作可以保证在执行期间不会被中断,从而避免了竞态条件。在C语言中,可以使用GCC内置的原子操作函数(如__sync_fetch_and_add)或者C11标准中的原子操作类型(如atomic_int)来实现线程安全的i++操作。 3. 使用线程局部存储(Thread-Local Storage):如果每个线程都有自己的i变量副本,那么就不会有竞态条件的问题。可以使用线程局部存储来实现每个线程都有独立的i变量。 需要注意的是,以上措施都需要根据具体情况和需求来选择和实现。在多线程环境下,对共享资源的访问需要谨慎处理,确保线程安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值