C++ Boost Atomic详细讲解

目录
  • 一、说明
  • 二、示例和代码

一、说明

Boost.Atomic 提供类 boost::atomic,可用于创建原子变量。它们被称为原子变量,因为所有访问都是原子的。 Boost.Atomic 用于多线程程序,当在一个线程中访问变量不应被访问相同变量的另一个线程中断时。如果没有 boost::atomic,从多个线程访问共享变量的尝试将需要与锁同步。

boost::atomic 取决于支持原子变量访问的目标平台。否则,boost::atomic 使用锁。该库允许您检测目标平台是否支持原子变量访问。

如果您的开发环境支持 C++11,则不需要 Boost.Atomic。 C++11 标准库提供了一个头文件 atomic,它定义了与 Boost.Atomic 相同的功能。例如,您会发现一个名为 std::atomic 的类。

Boost.Atomic 支持与标准库大致相同的功能。虽然一些函数在 Boost.Atomic 中被重载,但它们在标准库中可能有不同的名称。标准库还提供了一些 Boost.Atomic 中缺少的函数,例如 std::atomic_init() 和 std::kill_dependency()。

二、示例和代码

示例 45.1。使用 boost::atomic

Boost.Atomic

#include <boost/atomic.hpp>
#include <thread>
#include <iostream>
boost::atomic<int> a{ 0 };
void thread()
{
	++a;
}
void thread_s()
{
	std::cout << "Hello Thread" << a << '\n';
}
int main()
{
	std::thread t1{ thread };
	std::thread t2{ thread };
	std::thread t3{ thread_s };
	std::thread t4{ thread_s };
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	std::cout << a << '\n';
}

Example45.1

示例 45.1 使用两个线程来递增 int 变量 a。该示例使用 boost::atomic 代替锁来对 a 进行原子访问。该示例将 2 写入标准输出。

boost::atomic 之所以有效,是因为一些处理器支持对变量的原子访问。如果增加一个 int 变量是一个原子操作,则不需要锁。如果此示例在无法将变量递增为原子操作的平台上运行,则 boost::atomic 使用锁。

示例 45.2。 boost::atomic 带锁或不带锁

#include <boost/atomic.hpp>
#include <iostream>
int main()
{
  std::cout.setf(std::ios::boolalpha);
  boost::atomic<short> s;
  std::cout << s.is_lock_free() << '\n';
  boost::atomic<int> i;
  std::cout << i.is_lock_free() << '\n';
  boost::atomic<long> l;
  std::cout << l.is_lock_free() << '\n';
}

您可以在原子变量上调用 is_lock_free() 来检查是否在没有锁的情况下访问该变量。如果您在 Intel x86 处理器上运行示例,它会显示 true 三次。如果您在没有对 short、int 和 long 变量进行无锁访问的处理器上运行它,则会显示 false。

Boost.Atomic 提供了 BOOST_ATOMIC_INT_LOCK_FREE 和 BOOST_ATOMIC_LONG_LOCK_FREE 宏来在编译时检查哪些数据类型支持无锁访问。

示例 45.2 仅使用整型数据类型。您不应将 boost::atomic 与 std::string 或 std::vector 等类一起使用。 Boost.Atomic 支持整数、指针、布尔值 (bool) 和普通类。整数类型的示例包括 short、int 和 long。普通类定义可以使用 std::memcpy() 复制的对象。

示例 45.3。 boost::atomic 和 boost::memory_order_seq_cst

#include <boost/atomic.hpp>
#include <thread>
#include <iostream>
boost::atomic<int> a{0};
void thread()
{
  a.fetch_add(1, boost::memory_order_seq_cst);
}
int main()
{
  std::thread t1{thread};
  std::thread t2{thread};
  t1.join();
  t2.join();
  std::cout << a << '\n';
}

Example45.3E

示例 45.3 增加了两次——这次不是使用 operator++,而是调用 fetch_add()。成员函数 fetch_add() 可以采用两个参数:a 应该递增的数字和内存顺序。

内存顺序指定内存访问操作必须发生的顺序。默认情况下,这个顺序是不确定的,不依赖于代码行的顺序。只要程序表现得好像内存访问操作是按源代码顺序执行的,编译器和处理器就可以更改顺序。此规则仅适用于线程。如果使用多个线程,内存访问顺序的变化会导致程序运行错误。 Boost.Atomic 支持在访问变量时指定内存顺序,以确保内存访问在多线程程序中以所需的顺序发生。

注意

指定内存顺序可优化性能,但会增加复杂性并使编写正确代码变得更加困难。因此,在实践中,您应该有充分的理由使用内存顺序。

示例 45.3 使用内存顺序 boost::memory_order_seq_cst 将 a 递增 1。内存顺序代表顺序一致性。这是最严格的内存顺序。在 fetch_add() 调用之前出现的所有内存访问必须在执行此成员函数之前发生。在 fetch_add() 调用之后出现的所有内存访问都必须在执行此成员函数之后发生。编译器和处理器可以在调用 fetch_add() 之前和之后重新排序内存访问,但它们不得将内存访问从调用 fetch_add() 之前移动到调用之后,反之亦然。 boost::memory_order_seq_cst 是双向内存访问的严格边界。

到此这篇关于C++ Boost Atomic详细讲解的文章就介绍到这了,更多相关C++ Boost Atomic内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-11-19

C++&nbsp;Boost&nbsp;PointerContainer智能指针详解

目录 一.提要 二.智能指针Boost.PointerContainer 三.练习 一.提要 在 C++11 中,Boost.PointerContainer是另一个智能指针,一般是用来生成集合数据的,本文阐述这种指针的特点和用法. 二.智能指针Boost.PointerContainer 库 Boost.PointerContainer 提供专门用于管理动态分配对象的容器.例如,在 C++11 中,您可以使用 std::vector<std::unique_ptr<int>> 创

C++&nbsp;Boost&nbsp;shared_ptr共享指针详细讲解

目录 一.提要 二.智能指针boost::shared_ptr与boost::scoped_ptr 三.智能指针 boost::shared_ptr用法 示例1 示例2 示例3 示例4 示例5 一.提要 boost::shared_ptr是另一个智能指针,与 boost::scoped_ptr有很大不同,本文阐述这种区别. 二.智能指针boost::shared_ptr与boost::scoped_ptr 主要区别在于: boost::shared_ptr 不一定是对象的独占所有者. 所有权可以

C++&nbsp;boost&nbsp;scoped_ptr智能指针详解

目录 一.智能指针-唯一所有者 二.接口类分析 一.智能指针-唯一所有者 boost::scoped_ptr 是一个智能指针,它是动态分配对象的唯一所有者. boost::scoped_ptr 无法复制或移动.此智能指针在头文件 boost/scoped_ptr.hpp 中定义. 二.接口类分析 scoped_array 分析 scoped_array 的类部分原始代码如下: template<class T> class scoped_array // noncopyable { priva

C++&nbsp;Boost&nbsp;MPI接口详细讲解

目录 一.说明 二.开发和运行时环境 三.简单数据交换 一.说明 Boost.MPI 提供了 MPI 标准(消息传递接口)的接口.该标准简化了并发执行任务的程序的开发.您可以使用线程或通过共享内存或网络连接使多个进程相互通信来开发此类程序. MPI 的优点是你不需要关心这些细节.您可以完全专注于并行化您的程序. 缺点是您需要 MPI 运行时环境.如果您控制运行时环境,MPI 只是一个选项.例如,如果你想分发一个可以通过双击启动的程序,你将无法使用 MPI.虽然操作系统开箱即用地支持线程.共享内存

C++&nbsp;Boost&nbsp;Lambda表达式详解

目录 lambda表达式格式 说明Boost.Lambda lambda表达式格式 lambda表达式的格式 [捕捉列表](参数列表)mutable->返回值类型{ 语句部分 }; 其中参数列表.返回值类型是可选的,捕捉列表.函数体可以为空. 先来看一个较为简单的lamda表达式 int main(void) { auto add = [](int a, int b)->int {return a + b; }; cout << add(1, 2) << endl; r

C++&nbsp;Boost&nbsp;Lockfree超详细讲解使用方法

目录 一.说明 二.示例和代码 Boost.Lockfree 一.说明 Boost.Lockfree 提供线程安全和无锁容器.可以从多个线程访问此库中的容器,而无需同步访问. 在 1.56.0 版本中,Boost.Lockfree 只提供了两个容器:boost::lockfree::queue 类型的队列和 boost::lockfree::stack 类型的栈.对于队列,可以使用第二个实现:boost::lockfree::spsc_queue.此类针对只有一个线程写入队列和只有一个线程从队列

Java&nbsp;超详细讲解hashCode方法

目录 1.介绍一下hashCode方法 2.为什么需要hashCode方法? 3.hashCode(),equals()两种方法是什么关系? 4.为什么重写 equals 方法必须重写 hashcode 方法 ? 1.介绍一下hashCode方法 hashCode() 的作用是获取哈希码,也称为散列码,它实际上是返回一个int整数.这个哈希码的作用是确定该对象在哈希表中的索引位置. hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有 hashCo

C++超详细讲解隐藏私有属性和方法的两种实现方式

目录 例子 用抽象类解决问题 用Pimpl风格解决问题 总结 参考 在我们编写程序的时候,会将程序模块化,常见的就是用动态链接库的方式,然后导出函数接口或者类.而对于导出类的方式,作为模块的实现者,不论是给第三方使用或者自己的项目使用,应该都不太愿意暴露自己的私有属性和方法,个人碰到的主要有以下两个常见原因: 通过隐藏私有属性和方法,让被调用者猜不到其实现方式 私有方法中或者属性中,可能会存在一些第三方的头文件或者库的依赖,而对于被调用方来说不应该直接依赖 本文将介绍两种方式来满足以上的需求,一

SpringBoot超详细讲解集成Flink的部署与打包方法

目录 一.SpringBoot集成Flink 二.FlinkTask写法调整 三.打包插件 四.Flink的上传与运行 总结 一.SpringBoot集成Flink 其实没什么特别的,就把Flink依赖的包在pom引入就行了.只是FlinkTask的写法要小调整下,把相关依赖交给spring管理就行. 然后如果放弃Flink的Dashboard端监控task执行相关信息,那也可以在SpringBoot的启动类里调用就行,但是可能出现task的相关对象没有注入,这种都是小问题(实际就是spring

Mybatis超详细讲解构建SQL方法

目录 1 SQL 构建对象介绍 1.1.1 介绍 1.1.2 实现准备 2 查询功能的实现 3 新增功能的实现 4 修改功能的实现 5 删除功能的实现 1 SQL 构建对象介绍 1.1.1 介绍 我们之前通过注解开发时,相关 SQL 语句都是自己直接拼写的.一些关键字写起来比较麻烦.而且容易出错. MyBatis 给我们提供了 org.apache.ibatis.jdbc.SQL 功能类,专门用于构建 SQL 语句 1.1.2 实现准备 编写指定调用方法 package com.yyl.sql;

C++&nbsp;Boost&nbsp;Optional示例超详细讲解

目录 一.概述 二.Boost.Optional 一.概述 数据结构类似于容器,因为它们可以存储一个或多个元素.但是,它们与容器不同,因为它们不支持容器通常支持的操作.例如,使用本部分介绍的数据结构,不可能在一次迭代中访问所有元素. Boost.Optional 可以很容易地标记可选的返回值.使用 Boost.Optional 创建的对象要么是空的,要么包含单个元素.使用 Boost.Optional,您无需使用空指针或 -1 等特殊值来指示函数可能没有返回值. Boost.Tuple 提供了

C++&nbsp;Boost&nbsp;Variant示例超详细讲解

目录 一.提要 二.示例 一.提要 Boost.Variant 提供了一个类似于 union 的名为 boost::variant 的类.您可以将不同类型的值存储在 boost::variant 变量中.在任何时候只能存储一个值.分配新值时,旧值将被覆盖.但是,新值的类型可能与旧值不同.唯一的要求是这些类型必须作为模板参数传递给 boost::variant,这样它们才能为 boost::variant 变量所知. boost::variant 支持任何类型.例如,可以将 std::string

C++&nbsp;Boost&nbsp;PropertyTree示例超详细讲解

目录 一.提要 二.应用示例 练习 一.提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对.树形结构意味着一个树干存在许多分支,其中有许多树枝.文件系统是树结构的一个很好的例子.文件系统有一个带有子目录的根目录,这些子目录本身可以有子目录等等. 二.应用示例 要使用 boost::property_tree::ptree,请包含头文件 boost/property_tree/ptree.hpp.这是一个主头文

java反射超详细讲解

目录 Java反射超详解✌ 1.反射基础 1.1Class类 1.2类加载 2.反射的使用 2.1Class对象的获取 2.2Constructor类及其用法 2.4Method类及其用法 Java反射超详解✌ 1.反射基础 Java反射机制是在程序的运行过程中,对于任何一个类,都能够知道它的所有属性和方法:对于任意一个对象,都能够知道它的任意属性和方法,这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制. Java反射机制主要提供以下这几个功能: 在运行时判断任意一个对象所属

超详细讲解Linux C++多线程同步的方式

目录 一.互斥锁 1.互斥锁的初始化 2.互斥锁的相关属性及分类 3,测试加锁函数 二.条件变量 1.条件变量的相关函数 1)初始化的销毁读写锁 2)以写的方式获取锁,以读的方式获取锁,释放读写锁 四.信号量 1)信号量初始化 2)信号量值的加减 3)对信号量进行清理 背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通过多线程模拟多窗口售票为例: #include <iostream> #include<pthread.h> #include<stdio.h&

超详细讲解python正则表达式

目录 正则表达式 1.1 正则表达式字符串 1.1.1 元字符 1.1.2 字符转义 1.1.3 开始与结束字符 1.2 字符类 1.2.1 定义字符类 1.2.2 字符串取反 1.2.3 区间 1.2.4 预定义字符类 1.3 量词 1.3.1 量词的使用 1.3.2 贪婪量词和懒惰量词 1.4 分组 1.4.1 分组的使用 1.4.2 分组命名 1.4.3 反向引用分组 1.4.4 非捕获分组 1.5 re模块 1.5.1 search()和match()函数 1.5.2 findall()