一.前言
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