原子操作就是执行时不会被中断的指令。两个原子操作不可能同时作用于同一个变量,这个是原子操作的一个保证,至于处理器或者操作系统如何实现那是另外一回事。
内核提供了两个原子操作接口:一个是针对整型,其实也就是一个字,另一个针对单独的位。这些接口在不同的架构有不同的实现,大多数是直接支持简单的原子操作或者锁住内存总线以确保其他操作不能同时进行。可以想象下,简单的原子操作对应单处理器系统,对于多处理器系统就有必要对内存总线加锁了。另外有些架构如SPARC对原子操作指令的支持不足。
针对atomic_t而不是int来进行整型的原子操作的原因是:
1.确保原子操作只接收atomic_t类型的参数确保原子操作只对该类型有效,同时也保证该类型不会被传给非原子操作函数。
2.避免编译器自作聪明的优化,原子操作应该总是接收正确的内存地址。
3.可以隐藏架构独特性,如同pthread_t,或者反过来。
虽然atomic_t是个整型,也就是32位,但是以前一般只假定atomic_t不超过24位,这个跟SPARC有关,不过现在这个问题已经解决。
定义一个atomic_t变量很简单:
Atomic_t v;
Atomic_t u=ATOMIC_INIT(0);
下面是原子操作列表:
ATOMIC_INIT(int i) 申明变量时初始化为i
Int atomic_read(atomic_t *v) 读取变量v
Void atomic_set(atomic_t *v,int i) 把i赋给v
Void atomic_add(int i,atomic_t *v) v+i
Void atomic_sub(int i,atomic_t *v) v-i
Void atomic_inc(atomic_t *v) ++v
Void atomic_dec(atomic_t *v) --v
Int atomic_sub_and_test(int i,atomic_t *v)
v-i,如果结果为0,返回真(也就是1),否则返回假(也就是0)。呃。。。。好吧,俺啥也没说。
Int atomic_add_negative(int i,atommic_t *v) v+i,如果结果为负数返回真,否则返回假
Int atomic_dec_and_test(atomic *v) --v,如果为0返回真,否则返回假。
Int atomic_inc_and_test(atomic *v) ++v,如果为0返回真,否则返回假
这些原子操作通常是由inline汇编语句写的Inline函数实现的,通常也会是个宏。
需要区分下原子性与有序性:
读操作总是原子的,在大多数正常的架构中,如果一个整型初值为42然后被设置为365,对这个数的读操作要么返回42,要么返回365,而不可能是其他一个什么不知道是啥的数字,这就是原子性。
假如你需要一个读操作必须要在一个pending的写操作之前进行,这种行为就是有序性
原子性保证指令不会被中断并且要么完成要么失败。有序性保证几个指令的顺序,即便这些指令在不同的线程中。
通常原子操作总是优先选择的,因为简单。
to be continued...