多线程下变量-原子操作
最近阅读pachi的源代码,在多线程中需要对全局数据进行操作,看到__sync_fetch_and_add这种代码,下面是学习的整理。
事实上,C程序中简单的global_int++这种操作可以分为三部分:
- 从缓存中取出数据到寄存器
- 寄存器中数据累加
- 将数据从寄存器取到缓存
thread lock
因此多个线程并行对同一数据进行操作时,无法保证数据的正确性,因此多线程操作时通常需要上锁,保证同一时刻只能有一个线程在对数据进行操作,如下:
|
|
atomic variables
而__sync_fetch_and_add从处理器指令集层面对该功能进行了优化,该系列操作锁住FSB,这个FSB是处理器和RAM之间的总线,锁住了它,就能阻止其他处理器或者core从RAM获取数据,但是这种操作只适用于小片内存空间。Atomic variables在系统内核一直广泛使用,但是在用户层,直到gcc 4.1.2 才能使用。
性能差异
对上锁和atomic variables的性能进行了测试,代码见附录:
|
|
- 两种方式都可以保证线程安全
- atomic variables比加锁的方式快4.78(std 0.3468)倍(统计5次)
其他
该系列其他函数
type __sync_fetch_and_add (type *ptr, type value);
type __sync_fetch_and_sub (type *ptr, type value);
type __sync_fetch_and_or (type *ptr, type value);
type __sync_fetch_and_and (type *ptr, type value);
type __sync_fetch_and_xor (type *ptr, type value);
type __sync_fetch_and_nand (type *ptr, type value);
type __sync_add_and_fetch (type *ptr, type value);
type __sync_sub_and_fetch (type *ptr, type value);
type __sync_or_and_fetch (type *ptr, type value);
type __sync_and_and_fetch (type *ptr, type value);
type __sync_xor_and_fetch (type *ptr, type value);
type __sync_nand_and_fetch (type *ptr, type value);
数据类型只能是如下类型
- int
- unsigned int
- long
- unsigned long
- long long
- unsigned long long
refference
Multithreaded simple data type access and atomic variables
附录
|
|