c++ 原子操作
转载自:
http://blog.csdn.net/yockie/article/details/8838686
所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。 在以往的C++标准中并没有对原子操作进行规定,我们往往是使用汇编语言,或者是借助第三方的线程库,例如intel的pthread来实现。在新标准C++,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,提高了效率。 我们还是来看一个实际的例子。假若我们要设计一个广告点击统计程序,在服务器程序中,使用多个线程模拟多个用户对广告的点击: #include <boost/thread/thread.hpp>
#include <atomic>
#include <iostream>
#include <time.h> using namespace std;
// 全局的结果数据
long total = ; // 点击函数
void click()
{
for(int i=; i<;++i)
{
// 对全局数据进行无锁访问
total += ;
}
} int main(int argc, char* argv[])
{
// 计时开始
clock_t start = clock();
// 创建100个线程模拟点击统计
boost::thread_group threads;
for(int i=; i<;++i)
{
threads.create_thread(click);
} threads.join_all();
// 计时结束
clock_t finish = clock();
// 输出结果
cout<<"result:"<<total<<endl;
cout<<"duration:"<<finish -start<<"ms"<<endl;
return ;
} 从执行的结果来看,这样的方法虽然非常快,但是结果不正确
E:\SourceCode\MinGW>thread.exe
result:
duration:528ms 很自然地,我们会想到使用互斥对象来对全局共享资源的访问进行保护,于是有了下面的实现: long total = ;
// 对共享资源进行保护的互斥对象
mutex m; void click()
{
for(int i=; i<;++i)
{
// 访问之前,锁定互斥对象
m.lock();
total += ;
// 访问完成后,释放互斥对象
m.unlock();
}
}
互斥对象的使用,保证了同一时刻只有唯一的一个线程对这个共享进行访问,从执行的结果来看,互斥对象保证了结果的正确性,但是也有非常大的性能损失,从刚才的528ms变成了现在的8431,用了原来时间的10多倍的时间。这个损失够大。
E:\SourceCode\MinGW>thread.exe
result:
duration:8431ms 如果是在C++11之前,我们的解决方案也就到此为止了,但是,C++对性能的追求是永无止境的,他总是想尽一切办法榨干CPU的性能。在C++11中,实现了原子操作的数据类型(atomic_bool,atomic_int,atomic_long等等),对于这些原子数据类型的共享资源的访问,无需借助mutex等锁机制,也能够实现对共享资源的正确访问。 // 引入原子数据类型的头文件
#include <atomic> // 用原子数据类型作为共享资源的数据类型
atomic_long total();
//long total = 0; void click()
{
for(int i=; i<;++i)
{
// 仅仅是数据类型的不同而以,对其的访问形式与普通数据类型的资源并无区别
total += ;
}
} 我们来看看使用原子数据类型之后的效果如何:
E:\SourceCode\MinGW>thread.exe
result:
duration:2105ms 结果正确!耗时只是使用mutex互斥对象的四分之一!也仅仅是不采用任何保护机制的时间的4倍。可以说这是一个非常不错的成绩了。 原子操作的实现跟普通数据类型类似,但是它能够在保证结果正确的前提下,提供比mutex等锁机制更好的性能,如果我们要访问的共享资源可以用原子数据类型表示,那么在多线程程序中使用这种新的等价数据类型,是一个不错的选择。
c++ 原子操作的更多相关文章
- Linux的原子操作与同步机制
Linux的原子操作与同步机制 .进程1执行完“mov eax, [count]”后,寄存器eax内保存了count的值0.此时,进程2被调度执行,抢占了进程1的CPU的控制权.进程2执行“cou ...
- [转载]C#使用Interlocked进行原子操作
原文链接:王旭博客 » C# 使用Interlocked进行原子操作 什么是原子操作? 原子(atom)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operat ...
- 漫谈C++11 Thread库之原子操作
我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...
- 原子操作--ARM架构
说明:内核版本号为3.10.101 一.ARM架构中的原子操作实现 在原子操作(一)中我们已经提到,各个架构组织为“复仇者”联盟,统一了基本的原子变量操作,这里我们就拿atomic_dec(v)来看看 ...
- 锁&锁与指令原子操作的关系 & cas_Queue
锁 锁以及信号量对大部分人来说都是非常熟悉的,特别是常用的mutex.锁有很多种,互斥锁,自旋锁,读写锁,顺序锁,等等,这里就只介绍常见到的, 互斥锁 这个是最常用的,win32:CreateMute ...
- Java--如何使用sun.misc.Unsafe完成compareAndSwapObject原子操作
package com; import sun.misc.Unsafe; import java.lang.reflect.Field; /** * Created by yangyu on 16/1 ...
- java并发:线程同步机制之Volatile关键字&原子操作Atomic
volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...
- gcc提供的原子操作函数
gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作.其声明如下: type __sync_fetch_and_add (type *ptr, type ...
- i++是否原子操作
i++是否原子操作 不是原子操作.理由: 1.i++分为三个阶段: 内存到寄存器 寄存器自增 回内存 这三个阶段中间都可以被中断分离开. 2.++i首先要看编译器是怎么编译的, 某些编译器比如VC在 ...
- php原子操作,文件锁flock,数据库事务
php原子操作,文件锁flock,数据库事务 php没有继承posix标准支持的unix锁,只封装了一个linux系统调用flock(信号量也能做成锁),按理也是可以使用锁机制的,虽然效率低一点.ph ...
随机推荐
- Java之组合数组2
编写函数Fun,其功能是将两个两位数的正整数A.B合并为一个整数放在C中,将A数的十位和个位一次放在C的个位和十位上,A数的十位和个位一次放在C的百位和千位上.例如,当 A=16,B=35,调用该函数 ...
- 很全的corel图像分类,场景识别图像库
这是真正的Corel-5K图像集,共包含科雷尔(Corel)公司收集整理的5000幅图片,故名:Corel-5K,童鞋们可用于科学图像实验:分类.检索等.Corel-5k数据集是图像实验的事实标准数据 ...
- C# 序列化(二)二进制序列化的案例
这篇是针对上一篇讲序列化的文章的一个实际案例,WinForm程序的主界面如下:
- [TimusACM][1258]程序员撞墙的问题
(本文是从我的旧博客迁移过来的) 问题地址:http://acm.timus.ru/problem.aspx?space=1&num=1258 前几日在博客园看到这种在线测试的时候,有一种相见 ...
- php连接到数据库
html代码: <form action="php_mysql_add.php" method="post"> 用户名: <input typ ...
- 关于火狐浏览器不支持img onerror的办法
项目中,要使用到缺省图,除了火狐浏览器,其它浏览器都支持img onerror事件.我使用到的解决的办法就是给图片的外层标签加背景,背景图用的就是缺省图. 上代码 <img src=" ...
- js动态引入的四种方式
index.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:// ...
- 9.配置postfix空客户端
将本地邮件服务器配置充当为控客户端,已将所有邮件都转发到中央服务器以进行发送 1.postconf -e "relayhost=[mail.example.com]" 邮件被路由到 ...
- WInform启动另一个项目传值
背景:从A项目中登陆后,跳转到B项目的某个页面(B不再登陆). A项目启动进程: public Form1() { InitializeComponent(); } #region 调用进程 [Dll ...
- 封装底层Ajax
创建Ajax简易步骤:创建Ajax对象:var xhr=new XMLHttpRequest();链接服务器:xhr.open('get','a.php',true);发送请求或数据:xhr.send ...