首页 > 其他分享 >__sync_fetch_and_add函数

__sync_fetch_and_add函数

时间:2023-04-05 19:47:29浏览次数:28  
标签:__ sync value fetch add type ptr

(一)背景

实现多线程环境下的计数器操作,统计相关事件的次数. 当然我们知道,count++这种操作不是原子的。一个自加操作,本质是分成三步的:

1 从缓存取到寄存器
2 在寄存器加1
3 存入缓存。

由于时序的因素,多个线程操作同一个全局变量,会出现问题。这也是并发编程的难点。在目前多核条件下,这种困境会越来越彰显出来。 最简单的处理办法就是加锁保护,这也是我最初的解决方案。看下面的代码:

pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&count_lock);
    global_int++;
    pthread_mutex_unlock(&count_lock);

后来在网上查找资料,找到了__sync_fetch_and_add系列的命令,发现这个系列命令讲的最好的一篇文章,英文好的同学可以直接去看原文。Multithreaded simple data type access and atomic variables

(二)系列函数

__sync_fetch_and_add系列一共有十二个函数,有加/减/与/或/异或/等函数的原子性操作函数,__sync_fetch_and_add,顾名思义,先fetch,然后自加,返回的是自加以前的值。以count = 4为例,调用__sync_fetch_and_add(&count,1)之后,返回值是4,然后,count变成了5.

简单验证代码如下sync_fetch_add.c:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv){
    int count = 4;
    printf("111 count:%d\n",count);
    int retval = __sync_fetch_and_add(&count,10);

    printf("222 retval:%d\n",retval);
    printf("222 count:%d\n",count);

    return 0;
}

linux 系统中命令行执行:gdb -g -o sync_fetch_add sync_fetch_add.c

得到可执行文件,执行后得到如下结果:

./sync_fetch_add 
111 count:4
222 retval:4
222 count:14

有__sync_fetch_and_add,自然也就有__sync_add_and_fetch,呵呵这个的意思就很清楚了,先自加,在返回。他们的关系与i++和++i的关系是一样的。有了这个函数,对于多线程对全局变量进行自加,我们就再也不用理线程锁了。下面这行代码,和上面被pthread_mutex保护的那行代码作用是一样的,而且也是线程安全的。

在用gcc编译的时候要加上选项 -march=i686,我在执行上面代码时,gcc没加该参数,使用到的版本gcc version 4.4.7 20120313 , 上面代码能正常运行通过。

下面是这群函数的全部,无非是先fetch再运算,或者先运算再fetch。

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);

GCC 提供的原子操作 gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作。

其声明如下:

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, ...)

这两组函数的区别在于第一组返回更新前的值,第二组返回更新后的值。

标签:__,sync,value,fetch,add,type,ptr
From: https://www.cnblogs.com/imreW/p/17290674.html

相关文章

  • IntelliJ IDEA 2019 快捷键
    打开关闭左侧文件夹:Alt+1运行程序:Shift+F10编译程序:Ctrl+Shift+F10代码提示:Ctrl+Space格式化代码:Ctrl+Alt+L在方法间跳转:Ctrl+Alt+向上/向下箭头在文件间跳转:Ctrl+Tab查找文件:Ctrl+Shift+N查找类、方法:Ctrl+N查找文本:Ctrl+F替换文本:Ctrl......
  • 牛客小白月赛61 ABCE*
    https://ac.nowcoder.com/acm/contest/46597A-超市里扫货#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<LL,LL>PII;constLLMAXN=1e18,MINN=-MAXN,INF=0x3f3f3f3f;constLLN=2e6+10,M=3023;constLLmod=100000007;const......
  • Redis布隆过滤器的原理和安装使用
    前言本文讲述布隆过滤器(RedisBloom)的基本原理和安装使用。RedisBloom是什么?RedisBloom是Redis中过滤器模块,可以用来判断值是否存在,常用来解决缓存穿透问题。查询数据时,先用RedisBloom判断数据是否存在,不存在则直接返回,存在则从缓存/数据库获取后返回。比如查询接......
  • python-爬虫-css提取-写入csv-爬取猫眼电影榜单
    猫眼有一个电影榜单top100,我们将他的榜单电影数据(电影名、主演、上映时间、豆瓣评分)抓下来保存到本地的excle中本案例使用css方式提取页面数据,所以会用到以下库importtimeimportrequestsimportparsel#解析库,解析cssimportcsv#爬取的数据写入csv创建csv文件标头信息......
  • Auto Chess (双指针, 极角排序)
    题目大意:释放一个45都的技能去尽可能消灭更多的敌人(在一个平面里面)  思路:技能是无线长的,于是抛弃无用信息,只保留斜率即可然后利用双指针,或者二分去做即可 ......
  • Redis 在排行榜中的应用
    1.Redis的SortedSet数据类型1.1SortedSet数据类型的特点SortedSet有序集合是Redis提供的一种重要的数据类型。它是由不重复且有序的字符串元素组成的,而且每个元素都会关联一个double类型的分数,通过该分数来为集合中的成员进行从小到大的排序。SortedSet的......
  • 实验三
    实验任务1源码#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);voidprint_spaces(intn);voidprint_blank_lines(intn);intmain(){intline,......
  • Redis持久化RDB和AOF原理解析、使用和优缺点对比
    前言本文讲述Redis两种持久化方式RDB和AOF优缺点以及原理。为何需要持久化?Redis是基于内存操作的,进程终止、服务器宕机后内存数据会丢失,但是在很多使用场景中我们希望数据不丢失,服务重启之后数据还能恢复到停机前的状态,特别是使用Redis做数据库的情况。Redis持久化......
  • 实验3 函数应用编程
    1.实验任务1#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);voidprint_spaces(intn);voidprint_blank_lines(intn);intmain(){int......
  • 实验三
    实验任务1#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);voidprint_spaces(intn);voidprint_blank_lines(intn);intmain(){intline,col......