Gcc内置原子操作__sync_系列函数简述及例程

Gcc 4.1.2版本之后,对X86或X86_64支持内置原子操作。就是说,不需要引入第三方库(如pthread)的锁保护,即可对1、2、4、8字节的数值或指针类型,进行原子加/减/与/或/异或等操作。

  1. __sync_fetch_and_add系列一共有十二个函数,有加/减/与/或/异或/等函数的原子性操作函
__snyc_fetch_and_add : 先fetch然后自加,返回的是自加以前的值
__snyc_add_and_fetch : 先自加然后返回,返回的是自加以后的值 (参照 ++i 和 i++) __snyc_fetch_and_add的一个简单使用:
int count = 4;
__sync_fetch_and_add(&count, 1); // __sync_fetch_and_add(&count, 1) == 4
cout<<count<<endl; //--->count=5

2.对于多线程对全局变量进行自加,我们就再也不用理线程锁了。

下面这行代码,和上面被pthread_mutex保护的那行代码作用是一样的,而且也是线程安全的。

__sync_fetch_and_add( &global_int, 1 );

将__sync_系列17个函数声明整理简化如下:

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_fetch_and_add,速度是线程锁的6~7倍

type可以是1,2,4或者8字节长度的int类型,即:

int8_t
uint8_t int16_t
uint16_t int32_t
uint32_t int64_t
uint64_t

3.例程

并编写了一个简单小例子,测试多个工作线程同时对同一个全局变量g_iSum进行加法操作时,使用__sync_fetch_and_add()原子操作进行原子加法,和不使用原子操作进行普通加法,观察它们运行结果的区别。每个工作线程加500万次,共10个工作线程,预期结果是5000万。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h> int g_iFlagAtom = 1;
#define WORK_SIZE 5000000
#define WORKER_COUNT 10
pthread_t g_tWorkId[WORKER_COUNT];
int g_iSum; void* thr_work(void *arg)
{
printf("Work Thread %08X Startup\n", (unsigned int)pthread_self());
int i;
for(i = 0; i < WORK_SIZE; i++)
{
if(g_iFlagAtom)
__sync_fetch_and_add(&g_iSum, 1);
else
g_iSum++;
}
return NULL;
} void* thr_management(void *arg)
{
printf("Management Thread %08X Startup\n", (unsigned int)pthread_self());
int i;
for(i = 0; i < WORKER_COUNT; i++)
{
pthread_join(g_tWorkId[i], NULL);
} printf("All Work Thread Finished!\n");
return NULL;
} int main(int argc, const char* argv[])
{
pthread_t tManagementId;
pthread_create(&tManagementId, NULL, thr_management, NULL);
int i;
for(i = 0; i < WORKER_COUNT; i++)
{
pthread_create(&g_tWorkId[i], NULL, thr_work, NULL);
}
printf("create %d worker threads\n", i);
pthread_join(tManagementId, NULL);
printf("the sum:%d\n", g_iSum);
return 0;
}

不使用原子操作

将g_iFlagAtom = 0,即不使用原子操作,可以看到输出结果无法达到预期的50000000,而且每次执行都可能得到不同的值。

gcc -Wall -o atom atom.cc -l pthread
./atom

使用原子操作

将g_iFlagAtom = 1,即使用原子操作,可以看到输出结果为预期的50000000,而且每次执行都得到这个值不变。

gcc -Wall -o atom1 atom.cc -l pthread
./atom1

Gcc内置原子操作__sync_系列函数的更多相关文章

  1. GCC内置函数

    在C语言写的程序中,有时候没有包含头文件,直接调用一些函数,如printf,也不会报错,因为GCC内置和一些函数.如果包含了头文件,则去第三方库中链接这个函数,不再使用GCC内置的函数.每个编译器的内 ...

  2. gcc 内置函数

    关于gcc内置函数和c隐式函数声明的认识以及一些推测   最近在看APUE,不愧是经典,看一点就收获一点.但是感觉有些东西还是没说清楚,需要自己动手验证一下,结果发现需要用gcc,就了解一下. 有时候 ...

  3. Python内置的字符串处理函数整理

    Python内置的字符串处理函数整理 作者: 字体:[增加 减小] 类型:转载 时间:2013-01-29我要评论 Python内置的字符串处理函数整理,收集常用的Python 内置的各种字符串处理 ...

  4. 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  5. PHP内置的字符串处理函数

    字符串的特点    1.其他类型的数据用在字符串类型处理函数中,会自动将其转化成字符串后,在处理 <?php echo substr("abcdefghijklmn",2,4 ...

  6. (转)原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  7. 多线程面试题系列(3):原子操作 Interlocked系列函数

    上一篇中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是否运行出错.这也非常类似于统计一个网站每天有多少用户登录,每个用户登录用一个线程模拟,线程运行时会将 ...

  8. thinkPHP内置字符串截取msubstr函数用法详解

    作者:陈达辉 字体:[增加 减小] 类型:转载 时间:2016-11-15 我要评论 这篇文章主要介绍了thinkPHP内置字符串截取函数用法,结合实例形式分析了thinkPHP内置的字符串截取函数功 ...

  9. 秒杀多线程第三篇 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  10. python内置常用高阶函数(列出了5个常用的)

    原文使用的是python2,现修改为python3,全部都实际输出过,可以运行. 引用自:http://www.cnblogs.com/duyaya/p/8562898.html https://bl ...

随机推荐

  1. 估值为一亿的AI核心代码

    本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是: 无论用户说什么,首先把对方说的话在一行中原样打印出来: 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部 ...

  2. 等保测评之主机测评——Windows Sever

    目录 (一)身份鉴别 (二)访问控制 (三)安全审计 (四)入侵防范 (五)恶意代码防范 (六)可信验证 (七)数据完整性 (八)数据保密性 (九)数据备份恢复 (十)剩余信息保护 在测评过程中最为常 ...

  3. iOS性能优化之内存分析

    成功之前我们要做应该做的事情,成功之后我们才可以做喜欢做的事情.   从苹果的开发者文档里可以看到内存分类如下所示,其中 Leaked memory和 Abandoned memory 都属于应该释放 ...

  4. Python 哈希表的实现——字典

    哈喽大家好,我是咸鱼 接触过 Python 的小伙伴应该对[字典]这一数据类型都了解吧 虽然 Python 没有显式名称为"哈希表"的内置数据结构,但是字典是哈希表实现的数据结构 ...

  5. IP的电源管脚

    IP的电源管脚是个特殊的存在. 1.对于前度RTL集成,需要和IP vendor以及后端确认,集成与综合时是否需要将电源DVDD,AVDD,引出到top层. 2.绝大部分情况下IP的电源PIN是sup ...

  6. 神经网络优化篇:详解dropout 正则化(Dropout Regularization)

    dropout 正则化 除了\(L2\)正则化,还有一个非常实用的正则化方法--"Dropout(随机失活)". 假设在训练上图这样的神经网络,它存在过拟合,这就是dropout所 ...

  7. 华企盾DSC无缝替换亿赛通案例

    第一种方法无缝替换亿赛通案例 1. 把DSCClient.exe和DSCService.exe添加到亿赛通的加密控制策略中,关联类型设置为*.*|,配置为落地自动解密,包括其它程序也配置成落地自动解密 ...

  8. 如何通过port-forward命令在本地访问 k8s 集群服务

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享 概述 在我们访问k8s中的pod服务时,一般通过node port映射pod端口进行访问,还有一种是通过ingress或者i ...

  9. 使用cgroup控制内存

    关键文件 memory.limit_in_bytes memory.soft_limit_in_bytes memory.memsw.limit_in_bytes tasks cgroup.procs ...

  10. ElasticSearch之cat fielddata API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/fielddata?v=true&pretty" --cacert $ES ...