c++11 atomic的使用详解

std::atomic_flag

  std::atomic_flag是一个原子的布尔类型,可支持两种原子操作:

  • test_and_set, 如果atomic_flag对象被设置,则返回true; 如果atomic_flag对象未被设置,则设置之,返回false
  • clear. 清楚atomic_flag对象

  std::atomic_flag可用于多线程之间的同步操作,类似于linux中的信号量。使用atomic_flag可实现mutex.

#include <iostream>
#include <atomic>
#include <vector>
#include <thread>
#include <sstream>

std::atomic_flag lock = ATOMIC_FLAG_INIT;
std::stringstream stream;

void append_numer(int x)
{
 while (lock.test_and_set());
 stream << "thread#" << x << "\n";
 lock.clear();
}

int main()
{
 std::vector<std::thread> ths;
 for (int i=0; i<10; i++)
  ths.push_back(std::thread(append_numer, i));
 for (int i=0; i<10; i++)
  ths[i].join();
 std::cout << stream.str();
 return 0;
}

std::atomic

  std::atomic对int, char, bool等数据结构进行原子性封装,在多线程环境中,对std::atomic对象的访问不会造成竞争-冒险。利用std::atomic可实现数据结构的无锁设计。

#include <iostream>
#include <atomic>
#include <vector>
#include <thread>
#include <sstream>

std::atomic<bool> ready(false);
std::atomic_flag winner = ATOMIC_FLAG_INIT;

void count1m(int i)
{
 while (!ready);
 for (int i=0; i<1000000; i++);
 if (!winner.test_and_set())
  std::cout << "winner: " << i << std::endl;
}

int main()
{
 std::vector<std::thread> ths;
 for (int i=0; i<10; i++)
  ths.push_back(std::thread(count1m, i));
 ready = true;
 for (int i=0; i<10; i++)
  ths[i].join();
 return 0;
}

  在上例中,执行read=true之后,所有线程结束空等。winner被初始化为ATOMIC_FLAG_INIT,最先执行winner.test_and_set并返回false的线程为winner。

#include <iostream>
#include <atomic>
#include <vector>
#include <thread>
#include <sstream>

std::atomic<int> foo(0);

void set_foo(int x)
{
 foo = x;
}

void print_foo()
{
 while (foo == 0)
 {
  std::this_thread::yield();
 }
 std::cout << "x: " << foo << std::endl;
}
int main()
{
 std::thread print_th(print_foo);
 std::thread set_th(set_foo, 10);
 print_th.join();
 set_th.join();
 return 0;
}

  在上例总,set_foo用于设置atomic<int>对象的值,print_foo用于打印atomic<int>对象的值。std::atomic对象的值的读取和写入可使用load和store实现。

#include <iostream>
#include <cassert>
#include <atomic>
#include <vector>
#include <unistd.h>
#include <thread>
#include <sstream>

std::atomic<int> foo(0);
std::atomic_flag lock = ATOMIC_FLAG_INIT;

void add_foo()
{
 while (1)
 {
  foo++;
  // foo = foo + 1;
  while (lock.test_and_set());
  std::cout <<"add: " << foo << std::endl;
  lock.clear();
  usleep(1000);
 }
}

void sub_foo()
{
 while (1)
 {
  foo--;
  // foo = foo - 1;
  while (lock.test_and_set());
  std::cout << "sub: " << foo << std::endl;
  lock.clear();
  usleep(1000);
 }
}
int main()
{
 std::thread th2 = std::thread(add_foo);
 std::thread th1 = std::thread(sub_foo);
 th1.join();
 th2.join();
 return 0;
}

  atomic<int>支持++和--的原子操作。

以上就是c++11 atomic的使用详解的详细内容,更多关于c++11 atomic的使用的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++11并发编程关于原子操作atomic的代码示例

    一:概述 项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式. 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一个线程执行过程中可能被内核临时挂起,这就是线程切换,当内核再次切换到该线程时,之前的数据可能已被修改,不能保证原子操作. C++11提供了个原子的类和方法atomic,保证了多线程对变量原子性操作,相比加锁机制mutex.lock(),mutex.unlock(),性能有几倍的提升. 所需头文件<a

  • c++11 atomic的使用详解

    std::atomic_flag std::atomic_flag是一个原子的布尔类型,可支持两种原子操作: test_and_set, 如果atomic_flag对象被设置,则返回true; 如果atomic_flag对象未被设置,则设置之,返回false clear. 清楚atomic_flag对象 std::atomic_flag可用于多线程之间的同步操作,类似于linux中的信号量.使用atomic_flag可实现mutex. #include <iostream> #include

  • C++11 中的override详解

    目录 1 公有继承 1.1 纯虚函数 (pure virtual) 1.2 普通虚函数 1.2.1 方法一 1.2.2 方法二 1.3 非虚函数 2 重写 (override) 小结: 参考资料 1 公有继承 公有继承包含两部分:一是"函数接口" (interface),二是"函数实现" (implementation) 如 Shape 类中,三个成员函数,对应三种继承方式: class Shape { public: virtual void Draw() con

  • C++11中异常处理机制详解

    目录 一.异常的引入 二.C++异常的关键字 三.异常的抛出与处理规则 四.异常缺陷的处理 五.自定义异常体系 六.异常规范 七.异常安全 八.异常的优缺点 1.优点 2.缺点 一.异常的引入 传统的C语言处理异常的方式有两种: 1.终止程序:使用assert断言语句,如果发生内存错误等,比如内存泄漏或者除0错误,都会直接终止程序. 2.返回错误码:通过错误码判断发生的异常的类型是什么,如系统的很多库的接口程序通过把错误码放到errno中,表示错误. 在实际中的C语言程序基本都是通过返回错误码的

  • 64位Win10系统安装Mysql5.7.11的方法(案例详解)

    最近在装了64位Win10系统的mac book笔记本上用mysql-installer-community-5.7.11.0安装Mysql5.7.11,在配置mysql server时老是卡住,报错.(在别的PC相同windows系统,自动安装没问题),决定手动安装,依然问题多多,最后的成功安装案例如下: 一.准备安装软件 1.mysql.com下载mysql-5.7.11-win32.zip 2.mysql-workbench-community-6.3.6-win32.msi 3.vcre

  • Windows Vista中使用率最高的11条命令使用详解

    Vista被很多用户形容其太多华丽,所以带来了系统资源占用过多的局面,很多用户表示Vista做的太多了,但实际上如果你善于使用命令,以大大简化操作,甚至给你带来很多的惊喜. 下面给大家介绍十一个Windows Vista下最常到的命令,你只需在"运行框"输入相应的命令,便可享受命令行带来的异样乐趣. 一.远程协助: 这是个非常实用的功能,尤其是菜鸟,当你面对机器故障束手无策时,可以通过这个功能向Internet上的朋友的寻求帮助,让他直接在你机器上进行操作. 命令: msra.exe

  • 详解C++11原子类型与原子操作

    1.认识原子操作 原子操作就是在多线程程序中"最小的且不可并行化的"操作,意味着多个线程访问同一个资源时,有且仅有一个线程能对资源进行操作.通常情况下原子操作可以通过互斥的访问方式来保证,例如Linux下的互斥锁(mutex),Windows下的临界区(Critical Section)等.下面看一个Linux环境使用POSIX标准的pthread库实现多线程下的原子操作: #include <pthread.h> #include <iostream> usi

  • 详解C++之C++11的牛逼特性

    一.列表初始化 1.1 C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定. int array1[] = {1,2,3,4,5}; int array2[] = {0}; 对对于一些自定义类型,却不行. vector<int> v{1,2,3,4,5}; 在C++98中这样无法通过编译,因此需要定义vector之后,在使用循环进行初始赋值. C++11扩大了用初始化列表的使用范围,让其适用于所有的内置类型和自定义类型,而且使用时,=可以不写 // 内置类型 int x1

  • 详解c++ atomic原子编程中的Memory Order

    概述 但是,基于内核对象的同步,会带来昂贵的上下文切换(用户态切换到内核态,占用1000个以上的cpu周期).就需要使用另一种方法 -- 原子指令. 仅靠原子技术实现不了对资源的访问控制,即使简单计数操作,看上去正确的代码也可能会crash. 这里的关键在于编译器和cpu实施的重排指令导致了读写顺序的变化.只要没有依赖,代码中在后面的指令就可能跑到前面去,编译器和CPU都会这么做. 注1:单线程代码不需要关心乱序的问题.因为乱序至少要保证这一原则:不能改变单线程程序的执行行为 注2:内核对象多线

  • C++11 shared_ptr 与 make_shared源码剖析详解

    目录 0. 前言 1. 源码分析 1.1 头文件 1.2 构造 1.2.1 shared_ptr 的移动构造函数 1.2.2 shared_ptr 的拷贝构造函数 1.3 赋值重载 1.4 修改的接口 1.5 获取 2. make_shared 2.1 make_shared 优点 2.1.1 效率高 2.1.2 异常安全 2.2 make_shared缺点 3. 举例 参考: 总结 0. 前言 所谓智能指针,可以从字面上理解为"智能"的指针.具体来讲,智能指针和普通指针的用法是相似的

  • 详解C++11中的线程库

    目录 一.线程库的介绍 1.1. 使用时的注意点 1.2. 线程函数参数 1.3. join与detach 二.原子性操作库 2.1. atomic 2.2. 锁 三.使用lambda表达式创建多个线程 四.条件变量 一.线程库的介绍 在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差.C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念.要使用标

随机推荐