原子库为细粒度的原子操作提供组件,允许无锁并发编程。涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的。原子对象不具有数据竞争(data race)。原子类型对象的主要特点就是从不同线程访问不会导致数据竞争。因此从不同线程访问某个原子对象是良性(well-defined)行为,而通常对于非原子类型而言,并发访问某个对象(如果不做任何同步操作)会导致未定义(undifined)行为发生。

atomic是C++标准程序库中的一个头文件,定义了C++11标准中的一些表示线程、并发控制时原子操作的类与方法等。此头文件主要声明了两大类原子对象:std::atomic和std::atomic_flag,另外还声明了一套C风格的原子类型和与C兼容的原子操作的函数。在多线程并发执行时,原子操作是线程不会被打断的执行片段。一些程序设计更为注重性能和效率,需要开发lock-free的算法和数据结构,这就需要更为底层的原子操作与原子类型。原子类型对象的主要特点就是从不同线程并发访问是良性(well-defined)行为,不会导致竞争危害。与之相反,不做适当控制就并发访问非原子对象则会导致未定义(undifined)行为。

atomic_flag类:是一种简单的原子布尔类型,只支持两种操作:test_and_set(flag=true)和clear(flag=false)。跟std::atomic的其它所有特化类不同,它是锁无关的。结合std::atomic_flag::test_and_set()和std::atomic_flag::clear(),std::atomic_flag对象可以当作一个简单的自旋锁(spin lock)使用。atomic_flag只有默认构造函数,禁用拷贝构造函数,移动构造函数实际上也禁用。如果在初始化时没有明确使用宏ATOMIC_FLAG_INIT初始化,那么新创建的std::atomic_flag对象的状态是未指定的(unspecified),既没有被set也没有被clear;如果使用该宏初始化,该std::atomic_flag对象在创建时处于clear状态。

(1)、test_and_set:返回该std::atomic_flag对象当前状态,检查flag是否被设置,若被设置直接返回true,若没有设置则设置flag为true后再返回false。该函数是原子的。

(2)、clear:清除std::atomic_flag对象的标志位,即设置atomic_flag的值为false。

std::atomic类模板:std::atomic比std::atomic_flag功能更加完善。C++11标准库std::atomic提供了针对bool类型、整形(integral)和指针类型的特化实现。每个std::atomic模板的实例化和完全特化定义一个原子类型。若一个线程写入原子对象,同时另一个线程从它读取,则行为良好定义。而且,对原子对象的访问可以按std::memory_order所指定建立线程间同步,并排序非原子的内存访问。std::atomic可以以任何可平凡复制(Trivially Copyable)的类型T实例化。std::atomic既不可复制亦不可移动。

除了std::atomic和std::atomic_flag外,<atomic>还包括了基于std::atomic_flag类的C风格API和基于std::atomic类模板的C风格API。

与原子对象初始化相关的两个宏:

(1)、ATOMIC_VAR_INIT(val):初始化std::atomic对象。This macro expands to a token sequence suitable to initialize an atomic object (of static storage duration) with a value of val. This macro exists for compatibility with C implementations, in which it is used as a constructor-like function for(default-constructed) atomic objects; In C++, this initialization may be performed directly by the initialization constructor.

(2)、ATOMIC_FLAG_INIT:初始化std::atomic_flag对象。This macro is defined in such a way that it can be used to initialize an object of type atomic_flag to the clear state.

std::atomic:Objects of atomic types contain a value of a particular type (T). The main characteristic of atomic objects is that access to this contained value from different threads cannot cause data races (i.e., doing that is well-defined behavior, with accesses properly sequenced). Generally, for all other objects, the possibility of causing a data race for accessing the same object concurrently qualifies the operation as undefined behavior. Additionally, atomic objects have the ability to synchronize access to other non-atomic objects in their threads by specifying different memory orders.

std::atomic_flag:Atomic flags are boolean atomic objects that support two operations:test-and-set and clear.

下面是从其他文章中copy的<atomic>测试代码,详细内容介绍可以参考对应的reference:

#include "atomic.hpp"
#include <iostream>
#include <atomic>
#include <vector>
#include <thread>
#include <sstream>namespace atomic {
/
// reference: http://www.cplusplus.com/reference/atomic/atomic/atomic/
std::atomic<bool> ready(false);
// atomic_flag::atomic_flag: Constructs an atomic_flag object
// The atomic_flag is in an unspecified state on construction (either set or clear),
// unless it is explicitly initialized to ATOMIC_FLAG_INIT.
std::atomic_flag winner = ATOMIC_FLAG_INIT;void count1m(int id)
{while (!ready) { std::this_thread::yield(); }      // wait for the ready signalfor (volatile int i = 0; i < 1000000; ++i) {}          // go!, count to 1 millionif (!winner.test_and_set()) { std::cout << "thread #" << id << " won!\n"; }
};int test_atomic_atomic()
{// atomic::atomic: Constructs an atomic objectstd::vector<std::thread> threads;std::cout << "spawning 10 threads that count to 1 million...\n";for (int i = 1; i <= 10; ++i) threads.push_back(std::thread(count1m, i));ready = true;for (auto& th : threads) th.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/atomic/atomic/compare_exchange_weak/
// a simple global linked list:
struct Node { int value; Node* next; };
std::atomic<Node*> list_head(nullptr);void append(int val)
{     // append an element to the listNode* oldHead = list_head;Node* newNode = new Node{ val, oldHead };// what follows is equivalent to: list_head = newNode, but in a thread-safe way:while (!list_head.compare_exchange_weak(oldHead, newNode))newNode->next = oldHead;
}int test_atomic_compare_exchange_weak()
{// atomic::compare_exchange_weak: Compares the contents of the atomic object's contained value with expected:// -if true, it replaces the contained value with val(like store).// - if false, it replaces expected with the contained value// spawn 10 threads to fill the linked list:std::vector<std::thread> threads;for (int i = 0; i<10; ++i) threads.push_back(std::thread(append, i));for (auto& th : threads) th.join();// print contents:for (Node* it = list_head; it != nullptr; it = it->next)std::cout << ' ' << it->value;std::cout << '\n';// cleanup:Node* it; while (it = list_head) { list_head = it->next; delete it; }return 0;
}///
// reference: http://www.cplusplus.com/reference/atomic/atomic/exchange/
std::atomic<bool> winner_(false);void count1m_(int id)
{while (!ready) {}                  // wait for the ready signalfor (int i = 0; i<1000000; ++i) {}   // go!, count to 1 millionif (!winner_.exchange(true)) { std::cout << "thread #" << id << " won!\n"; }
};int test_atomic_exchange()
{// atomic::exchange: Replaces the contained value by val and returns the value it had immediately beforestd::vector<std::thread> threads;std::cout << "spawning 10 threads that count to 1 million...\n";for (int i = 1; i <= 10; ++i) threads.push_back(std::thread(count1m_, i));ready = true;for (auto& th : threads) th.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/atomic/atomic/load/
std::atomic<int> foo(0);void set_foo(int x)
{foo.store(x, std::memory_order_relaxed);     // set value atomically
}void print_foo()
{int x;do {x = foo.load(std::memory_order_relaxed);  // get value atomically} while (x == 0);std::cout << "foo: " << x << '\n';
}int test_atomic_load()
{// atomic::load: Returns the contained value.// The operation is atomic and follows the memory ordering specified by sync.std::thread first(print_foo);std::thread second(set_foo, 10);first.join();second.join();return 0;
}// reference: http://www.cplusplus.com/reference/atomic/atomic/operator=/
std::atomic<int> foo_ = 0;void set_foo_(int x)
{foo_ = x;
}void print_foo_()
{while (foo_ == 0) {             // wait while foo_=0std::this_thread::yield();}std::cout << "foo_: " << foo_ << '\n';
}int test_atomic_operator()
{// atomic::operator=: Replaces the stored value by val.// This operation is atomic and uses sequential consistency (memory_order_seq_cst).// To modify the value with a different memory orderingstd::thread first(print_foo_);std::thread second(set_foo_, 10);first.join();second.join();return 0;
}///
// reference: http://www.cplusplus.com/reference/atomic/atomic/store/
int test_atomic_store()
{// atomic::store: Replaces the contained value with val.// The operation is atomic and follows the memory ordering specified by sync.std::thread first(print_foo);std::thread second(set_foo, 10);first.join();second.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/atomic/atomic_flag/clear/
std::atomic_flag lock_stream = ATOMIC_FLAG_INIT;
std::stringstream stream;void append_number(int x)
{while (lock_stream.test_and_set()) {}stream << "thread #" << x << '\n';lock_stream.clear();
}int test_atomic_flag_atomic_clear()
{// atomic_flag::clear: Clears the atomic_flag (i.e., sets it to false)//Clearing the atomic_flag makes the next call to member atomic_flag::test_and_set on this object return false.// The operation is atomic and follows the memory ordering specified by sync.// atomic_flag::test_and_set: Sets the atomic_flag and returns whether it was already set immediately before the call// The entire operation is atomic (an atomic read-modify-write operation): the value is not affected by other threads// between the instant its value is read (to be returned) and the moment it is modified by this function.std::vector<std::thread> threads;for (int i = 1; i <= 10; ++i) threads.push_back(std::thread(append_number, i));for (auto& th : threads) th.join();std::cout << stream.str();return 0;
}} // namespace atomic

GitHub:https://github.com/fengbingchun/Messy_Test

C++11中头文件atomic的使用相关推荐

  1. C++11中头文件thread的使用

    C++11中加入了<thread>头文件,此头文件主要声明了std::thread线程类.C++11的标准类std::thread对线程进行了封装.std::thread代表了一个线程对象 ...

  2. C++11中头文件type_traits介绍

    C++11中的头文件type_traits定义了一系列模板类,在编译期获得某一参数.某一变量.某一个类等等类型信息,主要做静态检查. 此头文件包含三部分: (1).Helper类:帮助创建编译时常量的 ...

  3. C++11中头文件chrono的使用

    在C++11中,<chrono>是标准模板库中与时间有关的头文件.该头文件中所有函数与类模板均定义在std::chrono命名空间中. std::chrono是在C++11中引入的,是一个 ...

  4. C++/C++11中头文件sstream介绍

    C++使用标准库类来处理面向流的输入和输出:(1).iostream处理控制台IO:(2).fstream处理命名文件IO:(3).stringstream完成内存string的IO. 类fstrea ...

  5. C++/C++11中头文件functional的使用

    <functional>是C++标准库中的一个头文件,定义了C++标准中多个用于表示函数对象(function object)的类模板,包括算法操作.比较操作.逻辑操作:以及用于绑定函数对 ...

  6. C++11中头文件ratio的使用

    include<ratio>是在C++11中引入的,在此文件中有一些模板类. 模板类std::ratio及相关的模板类(如std::ratio_add)提供编译时有理数算术支持.此模板的每 ...

  7. C++/C++11中头文件algorithm的使用

    <algorithm>是C++标准程序库中的一个头文件,定义了C++ STL标准中的基础性的算法(均为函数模板).<algorithm>定义了设计用于元素范围的函数集合.任何对 ...

  8. C++/C++11中头文件numeric的使用

    <numeric>是C++标准程序库中的一个头文件,定义了C++ STL标准中的基础性的数值算法(均为函数模板): (1).accumulate: 以init为初值,对迭代器给出的值序列做 ...

  9. C++/C++11中头文件iterator的使用

    <iterator>是C++标准程序库中的一个头文件,定义了C++ STL标准中的一些迭代器模板类,这些类都是以std::iterator为基类派生出来的.迭代器提供对集合(容器)元素的操 ...

最新文章

  1. NumPy库入门教程:基础知识总结
  2. 风清杨之Oracle的安装与说明
  3. c++:用顺序表实现简单的栈
  4. Unreachable code
  5. ARouter 源码历险记 (一)
  6. linux的目录proc pid,Linux /proc第一篇----/proc/pid记录了什么
  7. Socket网络编程--小小网盘程序(5)
  8. 前端学习(1892)vue之电商管理系统电商系统之为表格添加索引列
  9. 一分钟了解四层/七层反向代理
  10. linux通过操作界面和命令行的方式查看ip地址、mac地址
  11. 拼多多网站的服务器多大,拼多多打不开网页怎么回事
  12. 指数函数 java_计算指数函数的算法
  13. 难以忽视的真相:谈及利润,iPhone‘独孤求败’
  14. 微信公众号登录和获得access_token和发送模板消息
  15. APICloud+vue+vant实现二维码扫码功能
  16. 【RuoYi-Vue-Plus】问题笔记 06 - p6spy 日志打印 SQL 时间格式化问题
  17. ClearCase 介绍 1
  18. scotland yard
  19. 算法python实现_Relief算法python实现
  20. 【热点解读】冬奥会上的中国元素

热门文章

  1. 编译 ORB_SLAM2 (一)
  2. 强化学习(八) - 深度Q学习(Deep Q-learning, DQL,DQN)原理及相关实例
  3. 关闭、刷新、跳转、离开当前网页前提示
  4. 强哥原创管理方法论之“粉丝经济管理学”
  5. 封装echarts china map geo实现dispatch触发geoSelect事件高亮显示某个省份和城市,并定义复杂样式
  6. ATS 6.2.1打release版本rpm包时插件中出现undefined symbol的问题追踪
  7. 在Ubuntu 14.04 64bit上升级安装ATS 5.3.2/6.1.1实录
  8. list_for_each_safe
  9. 2019年3月8日比赛(知网是什么)
  10. vagrant 介绍,安装与使用