原子操作

说明

原子操作是CPU提供的特性,不是每个CPU都支持,各个CPU的支持和底层实现并不一样,下面的例子只以Intel 架构来说明

例子
#include <stdio.h>
#include <pthread.h>

/*
        type __sync_fetch_and_add (type *ptr, type value, ...)
        __sync_fetch_and_add() / __sync_fetch_and_sub() / __sync_fetch_and_or ...
        equal to { tmp = *ptr; *ptr += value; return tmp; }
        返回旧值base_val
        并且base_val += val
*/
int getAndAdd(int *ptr, int val) {
        return __sync_fetch_and_add(ptr, val);
}

/*
        type __sync_add_and_fetch (type *ptr, type value, ...)
        __sync_add_and_fetch / __sync_sub_and_fetch  / __sync_or_and_fetch / __sync_and_and_fetch  ...
        equal to { *ptr op= value; return *ptr; }
        返回新值,新值 += value
*/
int addAndGet(int *ptr, int val) {
        return __sync_add_and_fetch(ptr, val);
}

/*
        type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
        equal to {
                tmp = *ptr;
                if (*ptr == oldval)
                        *ptr = newval;
                return tmp; }
        先保存*ptr在临时变量中
        判断如果*ptr是否和旧值相等,相等就将newval赋值给*ptr,不相等就不处理
        返回tmp
*/
int get(int *val) {
        return __sync_val_compare_and_swap(val, 0, 0);
}

/*
        __sync_synchronize (...)
        内存barrier,避免编译器进行指令前后的优化
*/
void memoryBarrier() {
        __sync_synchronize();
}

/*
        type __sync_lock_test_and_set (type *ptr, type value, ...)
        equal to {
                tmp = *ptr;
                *ptr = value;
                return tmp;
        }
        先保存旧值
        设置新值
        返回旧值
*/
int getAndSet(int *ptr, int val) {
        return __sync_lock_test_and_set(ptr, val);
}

int base_val = 12;
void *test_atomic(void *arg) {
        // 先打印值,再加一
        while (1) {
                int val = getAndAdd(&base_val, 1);
                //int val = base_val ++;
                memoryBarrier();
                if (val >= 1000) {
                        break;
                }
        }
        return NULL;
}

int main() {
        pthread_t p1, p2;

        pthread_create(&p1, NULL, test_atomic, NULL);
        pthread_create(&p2, NULL, test_atomic, NULL);

        pthread_join(p1, NULL);
        pthread_join(p2, NULL);

        printf("count: %d\n", base_val);
        return 0;
}

总结

  1. 原子操作只适用于1, 2, 4 或者 8字节的整数,指针操作
  2. 原子操作只会针对那一条语句有效,如果是多条原子操作堆砌起来的语句,还是不能起到原子操作的作用。比如说如下代码:
int val = getAndAdd(&base_val, 1);
// 在这个窗口不能保证原子操作
int tol = addAndGet(&base_val, 12);
...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值