GCC数值原子操作API原理及应用

一.前言

C/C++中数值操作,如自加(n++)自减(n–)及赋值(n=2)操作都不是原子操作,如果是多线程程序需要使用全局计数器,程序就需要使用锁或者互斥量,对于较高并发的程序,会造成一定的性能瓶颈。

二.gcc原子操作api

1.概要

为了提高赋值操作的效率,gcc提供了一组api,通过汇编级别的代码来保证赋值类操作的原子性,相对于涉及到操作系统系统调用和应用层同步的锁和互斥量,这组api的效率要高很多。

2.n++类

C
1
2
3
4
5
6
7
8
9
type __sync_fetch_and_add(type*ptr,type value,...); // m+n
type __sync_fetch_and_sub(type*ptr,type value,...); // m-n
type __sync_fetch_and_or(type*ptr,type value,...);    // m|n
type __sync_fetch_and_and(type*ptr,type value,...); // m&n
type __sync_fetch_and_xor(type*ptr,type value,...); // m^n
type __sync_fetch_and_nand(type*ptr,type value,...); // (~m)&n
/* 对应的伪代码 */
{tmp=*ptr;*ptr op=value; returntmp;}
{tmp=*ptr;*ptr=(~tmp)&value; returntmp;}    // nand

3.++n类

C
1
2
3
4
5
6
7
8
9
type __sync_add_and_fetch(type*ptr,type value,...); // m+n
type __sync_sub_and_fetch(type*ptr,type value,...); // m-n
type __sync_or_and_fetch(type*ptr,type value,...); // m|n
type __sync_and_and_fetch(type*ptr,type value,...); // m&n
type __sync_xor_and_fetch(type*ptr,type value,...); // m^n
type __sync_nand_and_fetch(type*ptr,type value,...); // (~m)&n
/* 对应的伪代码 */
{*ptr op=value; return*ptr;}
{*ptr=(~*ptr)&value; return*ptr;} // nand

4.CAS类

C
1
2
3
4
5
bool__sync_bool_compare_and_swap(type*ptr,type oldval,type newval,...);
type __sync_val_compare_and_swap(type*ptr,type oldval,type newval,...);
/* 对应的伪代码 */
{ if(*ptr==oldval){*ptr=newval; return true;} else{ return false;}}
{ if(*ptr==oldval){*ptr=newval;} returnoldval;}

三.程序实例

1.test.c

例子不是并发的程序,只是演示各api的使用参数和返回。由于是gcc内置api,所以并不需要任何头文件。

test.c
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
 
intmain(){
     intnum= 0;
 
     /*
     * n++;
     * __sync_fetch_and_add(10, 3) = 10
     * num = 13
     */
    num= 10;
     printf( "__sync_fetch_and_add(%d, %d) = %d\n", 10, 3,__sync_fetch_and_add(&num, 3));
     printf( "num = %d\n",num);
 
     /*
     * ++n;
     * __sync_and_add_and_fetch(10, 3) = 13
     * num = 13
     */
    num= 10;
     printf( "__sync_and_add_and_fetch(%d, %d) = %d\n", 10, 3,__sync_add_and_fetch(&num, 3));
     printf( "num = %d\n",num);
 
     /*
     * CAS, match
     * __sync_val_compare_and_swap(10, 10, 2) = 10
     * num = 2
     */
    num= 10;
     printf( "__sync_val_compare_and_swap(%d, %d, %d) = %d\n", 10, 10, 2,__sync_val_compare_and_swap(&num, 10, 2));
     printf( "num = %d\n",num);
 
     /*
     * CAS, not match
     * __sync_val_compare_and_swap(10, 3, 5) = 10
     * num = 10
     */
    num= 10;
     printf( "__sync_val_compare_and_swap(%d, %d, %d) = %d\n", 10, 3, 5,__sync_val_compare_and_swap(&num, 1, 2));
     printf( "num = %d\n",num);
 
     return 0;
}

四.Reference

(1)gcc Atomic-Builtins doc
(2)CAS(Compare-and-swap)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值