C++11中的原子操作(atomic operation)

转载 2013年04月23日 10:57:49

所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。

在以往的C++标准中并没有对原子操作进行规定,我们往往是使用汇编语言,或者是借助第三方的线程库,例如intel的pthread来实现。在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,提高了效率。

我们还是来看一个实际的例子。假若我们要设计一个广告点击统计程序,在服务器程序中,使用多个线程模拟多个用户对广告的点击:

#include <boost/thread/thread.hpp>
#include <atomic> 
#include <iostream>
#include <time.h>

using namespace std;
// 全局的结果数据 
long total = 0; 

// 点击函数
void click()
{
    for(int i=0; i<1000000;++i)
    {
        // 对全局数据进行无锁访问 
        total += 1;     
    }
}
 
 
int main(int argc, char* argv[])
{
    // 计时开始
    clock_t start = clock();
    // 创建100个线程模拟点击统计
    boost::thread_group threads;
    for(int i=0; i<100;++i) 
    {
        threads.create_thread(click);
    }

    threads.join_all();
    // 计时结束
    clock_t finish = clock();
    // 输出结果
    cout<<"result:"<<total<<endl;
    cout<<"duration:"<<finish -start<<"ms"<<endl;
    return 0;
}

从执行的结果来看,这样的方法虽然非常快,但是结果不正确
E:\SourceCode\MinGW>thread.exe
result:87228026
duration:528ms

很自然地,我们会想到使用互斥对象来对全局共享资源的访问进行保护,于是有了下面的实现:

long total = 0;
// 对共享资源进行保护的互斥对象
mutex m;

void click()
{
    for(int i=0; i<1000000;++i)
    {
        // 访问之前,锁定互斥对象
        m.lock();
        total += 1;
        // 访问完成后,释放互斥对象 
        m.unlock();
    }
}
互斥对象的使用,保证了同一时刻只有唯一的一个线程对这个共享进行访问,从执行的结果来看,互斥对象保证了结果的正确性,但是也有非常大的性能损失,从刚才的528ms变成了现在的8431,用了原来时间的10多倍的时间。这个损失够大。
E:\SourceCode\MinGW>thread.exe
result:100000000
duration:8431ms

如果是在C++11之前,我们的解决方案也就到此为止了,但是,C++对性能的追求是永无止境的,他总是想尽一切办法榨干CPU的性能。在C++11中,实现了原子操作的数据类型(atomic_bool,atomic_int,atomic_long等等),对于这些原子数据类型的共享资源的访问,无需借助mutex等锁机制,也能够实现对共享资源的正确访问。

// 引入原子数据类型的头文件
#include <atomic> 
 

// 用原子数据类型作为共享资源的数据类型
atomic_long total(0);
//long total = 0;
 
void click()
{
    for(int i=0; i<1000000;++i)
    {
        // 仅仅是数据类型的不同而以,对其的访问形式与普通数据类型的资源并无区别
        total += 1;
    }
}

我们来看看使用原子数据类型之后的效果如何:
E:\SourceCode\MinGW>thread.exe
result:100000000
duration:2105ms

结果正确!耗时只是使用mutex互斥对象的四分之一!也仅仅是不采用任何保护机制的时间的4倍。可以说这是一个非常不错的成绩了。

原子操作的实现跟普通数据类型类似,但是它能够在保证结果正确的前提下,提供比mutex等锁机制更好的性能,如果我们要访问的共享资源可以用原子数据类型表示,那么在多线程程序中使用这种新的等价数据类型,是一个不错的选择。

【转自:http://imcc.blogbus.com/logs/179131763.html】

C++并发实战16: std::atomic原子操作

针对原子类型操作要不一步完成,要么不做,防止由于多线程串行化带来的错误。 1  std::atomic_flag是一个bool原子类型,其支持test_and_set和clear两个操作,atomic...
  • liuxuejiang158
  • liuxuejiang158
  • 2013年12月19日 15:50
  • 21770

C++多线程-第一篇-Atomic-原子操作

此系列基于Boost库多线程,但是大部分都在C++11中已经实现,所以两者基本一致。没什么特殊要求,练手还是C++11吧,方便不用配置。 PS:Boost不愧为C++准标准库。 本来不打算写,毕竟...
  • hffhjh111
  • hffhjh111
  • 2016年11月12日 15:17
  • 2266

C++11中<atomic>的使用

C++11中的使用
  • fengbingchun
  • fengbingchun
  • 2017年06月18日 19:13
  • 807

C++11多线程(九):《atomic类型详解一:atomic_flag介绍》

参考连接: http://www.cnblogs.com/haippy/p/3252056.html 不错的博客 http://www.cplusplus.com/reference/futu...
  • ceasadan
  • ceasadan
  • 2016年01月05日 16:58
  • 621

原子操作及对C++编程的意义

介绍 所谓原子操作,就是“不可中断的一个或一系列操作”。 在C/C++标准中,一个变量除了使用atomic相关的函数和编译器自带的一些扩展函数(interlocked系列函数)以外,  不保证所有的操...
  • ForYourFace
  • ForYourFace
  • 2015年11月06日 18:55
  • 1636

第五章 C++的内存模型和原子操作

5.1 Memory model basics (内在模型基础) Memory model 涉及两个方面:structural 和 concurrency structural 是基础,主要是对象...
  • XJF199001
  • XJF199001
  • 2016年07月10日 11:21
  • 727

C++11多线程(十):atomic原子操作的高效率(实例)

参考链接:http://blog.csdn.net/yockie/article/details/8838686 目录 1.原子操作介绍 2.示例比较:不用锁及原子(结果错误) 3.示例比较:用锁(...
  • ceasadan
  • ceasadan
  • 2016年01月06日 10:28
  • 2402

C++小品:榨干性能:C++11中的原子操作(atomic operation)

所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线...
  • abcd1f2
  • abcd1f2
  • 2015年11月03日 13:36
  • 1031

C++11:原子操作

在多线程开发中,为了确保数据安全性,经常需要对数据进行加锁、解锁处理。C++11中引入了原子的概念,简而言之就是访问它时它自动加锁解锁,从而使软件开发更为简便。 原子可谓一个既简单又复杂的概念。简单...
  • fawdlstty
  • fawdlstty
  • 2015年10月29日 15:03
  • 1870

C++ 中的原子性操作

在多进程(线程)访问资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源。原子操作(atomic operation)是不需要synchronized,这是Java多线程编程的老生常...
  • u011676589
  • u011676589
  • 2013年09月03日 21:57
  • 3909
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++11中的原子操作(atomic operation)
举报原因:
原因补充:

(最多只允许输入30个字)