多线程(12)atomic 原子操作系列接口

1. 原子操作

所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断。也就说,它是最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。
  总结就是: 不可中断的操作。

1.1 atomic_t 源码定义

linux专门定义了一种只进行原子操作的类型atomic_t

typedef struct {  
	volatile int counter;  
} atomic_t;  

原子变量作用:
主要是防止读取的是寄存器的内容,而内存的值已经被其他线程改变,主要是因为多线程的原因

本质: 原子类型其实是int类型,只是禁止寄存器对其暂存。

volatile 关键字
https://mp.csdn.net/mp_blog/creation/success/105363581

2. 使用场景

原子操作主要用于实现资源计数
很多引用计数(refcnt)就是通过原子操作实现的。

3. 接口

atomic_read(atomic_t * v); //原子读操作,它返回原子类型的变量v的值
atomic_set(atomic_t * v, int i);//设置原子类型的变量v的值为i
void atomic_add(int i, atomic_t *v); //给原子类型的变量v增加值i
atomic_sub(int i, atomic_t *v);	//从原子类型的变量v中减去i。
int atomic_sub_and_test(int i, atomic_t *v); //从原子类型的变量v中减去i,
							并判断结果是否为0,如果为0,返回真,否则返回假。 
void atomic_inc(atomic_t *v); //对原子类型变量v原子地增加1。 
void atomic_dec(atomic_t *v); //对原子类型的变量v原子地减1。
int atomic_add_negative(int i, atomic_t *v);//对原子类型的变量v原子地增加I,
							并判断结果是否为负数,如果是,返回真,否则返回假。 
int atomic_add_return(int i, atomic_t *v);//对原子类型的变量v原子地增加i,并且返回指向v的指针。 
int atomic_sub_return(int i, atomic_t *v);//从原子类型的变量v中减去i,并且返回指向v的指针。 
int atomic_inc_return(atomic_t * v);//对原子类型的变量v原子地增加1并且返回指向v的指针。 
int atomic_dec_return(atomic_t * v);//对原子类型的变量v原子地减1并且返回指向v的指针。

4. 例子

atomic_t  stCount;    
atomic_set(&(stCount), 0); /* 初始化 */
atomic_inc(&(stCount));/* 累加 */
unsigned int iRet = (unsigned int)atomic_read(&(stCount)); /* 读取 */

5. 扩展:atomic_add_unless

	int atomic_add_unless(atomic_t *v, int a, int u)

功能:

	如果 v!=u 则 v+=a 	 返回非0 
	如果 v=u  则 不处理v  返回0 

参数说明

	v:原子类型变量指针。关于原子类型atomic_t的定义参考atomic_set()函数的分析。
	a:整型值,在v的值不为u时,原子类型变量的值将在其原有基础上增加该变量值。
	u:整型值,被用来与v的值进行比较来决定是否对v进行增加a。

返回值:

	返回一个整型值,如果起初原子类型v的值即与u相等,则返回0,否则返回非0值。

例子:

(VOID)atomic_add_unless(&pstStatHashNode->stActiveConnections, -1, 0);
就是 stActiveConnections-1

源码实现:

static inline int atomic_cmpxchg(atomic_t *v, int old, int new)  
{  
    int ret;  
    unsigned long flags;  
  
    raw_local_irq_save(flags);  
    ret = v->counter;  
    if (likely(ret == old))  
        v->counter = new;  
    raw_local_irq_restore(flags);  
  
    return ret;  
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)  
{  
	int c, old;  
  
	c = atomic_read(v);  
	while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)  
		c = old;  
	return c != u;  
}

参考

https://www.cnblogs.com/still-smile/p/11652788.html
https://www.cnblogs.com/wanghuaijun/p/7705045.html

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值