【C++】多线程(二):std::mutex std::atomic的使用

这篇文章接着上一篇,继续介绍C++中的多线程。

推荐先阅读上一篇 【C++】多线程(一):std::thread的使用

互斥

我们前面的函数,无论是线程之间,还是线程和主线程之间,都是没有数据交换的。 接下来让多个线程操作一个全局变量试试。

int global_num = 0;void plus1000()
{for (int i = 0; i < 1000; i++)global_num++;
}int main()
{thread ths[10];for (auto &th : ths)th = thread(plus1000);for (auto &th : ths)th.join();cout << "n = " << global_num << endl;return 0;
}

运行结果并不是固定的,很奇怪。只有第一次出现了结果异常的,后续都是正常的。即使我把生成的 exe 删掉,结果也是正常的。

[Running] cd "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\" && g++ ThreadTest.cpp -o ThreadTest && "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\"ThreadTest
n = 9059[Done] exited with code=0 in 3.399 seconds[Running] cd "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\" && g++ ThreadTest.cpp -o ThreadTest && "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\"ThreadTest
n = 10000[Done] exited with code=0 in 1.189 seconds[Running] cd "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\" && g++ ThreadTest.cpp -o ThreadTest && "d:\Codes\CPP\VSCodeProjects\Nov\ThreadTest\"ThreadTest
n = 10000

如果这里针对全局变量的操作是单线程的,就不会有数据异常的问题。要解决这个问题,需要用到两个变量。

std::mutex

mutex又称互斥量,C++ 11中与 mutex相关的类(包括锁类型)和函数都声明在 mutex 头文件中,所以如果你需要使用 std::mutex,就必须包含 mutex 头文件。然后在适当的地方声明一个 mutex 变量即可。

mutex mtx;

在操作全局变量前对 mutex 上锁,操作完解锁,就可以避免数据异常的问题。

void plus1000()
{for (int i = 0; i < 1000; i++){mtx.lock();global_num++;mtx.unlock();}
}

不停地加锁和解锁会消耗 CPU 的性能,也会延长程序的运行时间。C++ 有很多对程序进行计时的函数,我们这里使用 Windows 平台的一个函数。

QueryPerformanceCounter()是一个Windows API,所需头文件为<windows.h>

这个函数返回高精确度性能计数器的值,它可以以微妙为单位计时.但是QueryPerformanceCounter()
确切的精确计时的最小单位是与系统有关的,

所以,必须要查询系统以得到QueryPerformanceCounter()返回的嘀哒声的频率.
QueryPerformanceFrequency() 提供了这个频率值,返回每秒嘀哒声的个数.

void plus1000()
{for (int i = 0; i < 1000; i++){mtx.lock();global_num++;mtx.unlock();}
}int main()
{LARGE_INTEGER t1,t2,tc;QueryPerformanceFrequency(&tc);QueryPerformanceCounter(&t1);thread ths[10];for (auto &th : ths)th = thread(plus1000);for (auto &th : ths)th.join();QueryPerformanceCounter(&t2);cout << "n = " << global_num << ", total time = " << (double)(t2.QuadPart-t1.QuadPart)/(double)tc.QuadPart << endl;return 0;
}

输出的结果为

n = 10000, total time = 0.0003675

std::atomic

atom 意为 原子,即不可分割的最小操作。理解这个需要一点操作系统多线程的知识。

回到 C++ 来说,需要引入头文件atomic,将 int 的声明方式改为 atomic_int 或者atomic<int>

atomic_int global_num = 0;

这两个是一样的,从源代码可以看出来:

  /// atomic_inttypedef atomic<int>			atomic_int;

即可去掉 mutex 锁,依然 能保证多线程下数据不会出现异常。这时的输出为:

n = 10000, total time = 0.0003647

感觉其实也没差多少,我更愿意理解为误差。

async 异步

thread在使用的时候有个很大的问题,就是没法获取函数的返回值。(不过,如果你是一个写过一些 C++ 代码的人,你应该熟悉使用引用参数替代返回值的写法,这里就不展开了),另外功能上也没有 async 全面。

事实上,thread 是一定会创建一个新的线程的,但 async 不一定,这在系统资源紧张的时候尤为明显,此时强行创建一个新的线程有概率导致程序崩溃。总之,先写个程序吧。

#include <iostream>
#include <future>using namespace std;int main()
{async([]{ cout << "Maybe a new thread?" << endl; });cout << "Yeah, u r right!" << endl;return 0;
}

和 thread 不一样,async 是个函数,其声明如下:

    async(_Fn&& __fn, _Args&&... __args){return std::async(launch::async|launch::deferred,std::forward<_Fn>(__fn),std::forward<_Args>(__args)...);}async(launch __policy, _Fn&& __fn, _Args&&... __args)

第一个参数即你希望 async 以什么样的方式执行 fun,

标识符作用
launch::async开启一个新线程立刻执行fun
launch::deferred不立刻执行fun,而是延迟到调用获取结果get的时候再执行,此时也不会开启新的线程
std::launch::async or std::launch::deferred由操作系统决定采用以上哪种方式,当没有传入launch参数时,此为参数的默认值
  /// Launch code for futuresenum class launch{async = 1,deferred = 2};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK3568平台开发系列讲解(Linux系统篇)netlink 监听广播信息

** 🚀返回专栏总目录 文章目录 一、什么是netlink 机制二、netlink 的使用2.1、创建 socket2.2、绑定套接字2.3、接收数据沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍如何通过 netlink 监听广播信息。 一、什么是netlink 机制 Netlink 是 Linux 内核中…

企业计算机服务器locked1勒索病毒数据恢复,locked1勒索病毒解密流程

随着计算机技术的不断发展&#xff0c;越来越多的企业走向数字化办公时代&#xff0c;计算机技术为企业的生产运营提供了有利条件&#xff0c;但也为企业带来了网络安全威胁。在本月&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的速达办公软件遭到了lo…

zemax之初级像差理论与像差校正——像散

1.像散的概念 像散是指轴外物点发出的锥形光束通过光学系统聚焦后&#xff0c;光斑在像面上子午方向与弧矢方向的不一致性。轴外视场光束通过光瞳后&#xff0c;在子午方向与弧矢的光程不相等&#xff0c;造成两个方向光斑分离所形成的弥散斑&#xff0c;称为光学系统的像散。…

LeetCode二分查找:x 的平方根

LeetCode二分查找&#xff1a;x 的平方根 题目描述 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 **注意&#xff1a;**不允许使用任何内置指数函数和算符&#x…

js中setinterval怎么用?怎么才能让setinterval停下来?

setinterval()是定时调用的函数&#xff0c;可按照指定的周期&#xff08;以毫秒计&#xff09;来调用函数或计算表达式。 setinterval()的作用是在播放动画的时&#xff0c;每隔一定时间就调用函数&#xff0c;方法或对象。 setInterval() 方法会不停地调用函数&#xff0c;…

Leetcode刷题详解——乘积最大子数组

1. 题目链接&#xff1a;152. 乘积最大子数组 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续子数组&#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位…

安全SCDN对网站蜘蛛抓取有影响吗,使用SCDN对百度蜘蛛抓取有否好处

目前网站使用德迅云安全SCDN情况非常普遍&#xff0c;但也有些客户是第一次了解使用SCDN&#xff0c;会有担心一个百度蜘蛛抓取问题&#xff0c;担心使用了SCDN之后会影响百度蜘蛛抓取。其实是完全不必担心这个的&#xff0c;从理论上来讲&#xff0c;使用了SCDN并不会影响百度…

【Collection - LinkedList源码解析】

本文主要对Collection - LinkedList进行源码解析。 Collection - LinkedList源码解析 概述LinkedList实现 底层数据结构构造函数getFirst(), getLast()removeFirst(), removeLast(), remove(e), remove(index)add()addAll()clear()Positional Access 方法查找操作Queue 方法Deq…

【大学英语视听说上】Mid-term Test 2

Section A 【短篇新闻1】 You probably think college students are experts at sleeping, but parties, preparations for tests, personal problems and general stress can rack a students sleep habits, which can be bad for the body and the mind. Texas Tech Univer…

JavaWeb(一)

一、Javaweb介绍 Web&#xff1a;全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏览器访问的网站。 JavaWeb&#xff1a;使用Java技术进行web互联网开发。 总结: 1、JavaWeb就是使用Java技术进行web互联网开发 2、一个web项目包含三个部分&#xff0c;分别…

【论文阅读】-使用小波变换进行数字图像模糊检测

使用小波变换进行数字图像模糊检测 文章目录 使用小波变换进行数字图像模糊检测1、论文提出的背景2、论文提出的模糊检测方案2.1 不同边缘的模糊效果2.2 边缘类型和锐度检测2.3 方案实现步骤3、论文方案Python实现4、实验结果及总结本文将详细介绍 Hanghang Tong 、Mingjing Li…

分页助手入门以及小bug,报sql语法错误

导入坐标 5版本以上的分页助手 可以不用手动指定数据库语言&#xff0c;它会自动识别 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency&g…

(C语言)逆序输出字符串

#include<stdio.h> #include<string.h> int main() {int i;char s[100];scanf("%s",&s);int count strlen(s);for(int i count -1;i > 0; i --)printf("%c",s[i]);return 0;} 代码运行截图&#xff1a; 注&#xff1a;侵权可删

10个高级技巧提升你的Python代码Level!!!(建议收藏)

Python是一种功能强大且广泛应用于各个领域的编程语言。无论你是初学者还是有一定经验的开发者&#xff0c;掌握一些高级技巧可以大大提升你的Python编程能力&#xff0c;使你的代码更加高效、可靠和易于维护。本文将介绍10个提升Python编程技能的高级技巧&#xff0c;帮助你在…

五子棋AI算法自动测试方法

先前发了几篇五子棋游戏程序设计的博文&#xff0c;设计了游戏程序&#xff0c;也设计了AI智能奕棋的算法&#xff0c;运行程序检测算法的可行性&#xff0c;完成人机模式游戏功能的设置。 本文主要介绍自动测试算法的方法。 AI智能奕棋的算法testAIq( )&#xff0c;主要是检测…

前端项目打包和自动化部署(jenkins+gitee+nginx)

项目打包和自动化部署 一. 项目部署和DevOps 1. 传统的开发模式 在传统的开发模式中&#xff0c;开发的整个过程是按部就班就行&#xff1a; 但是这种模式存在很大的弊端&#xff1a; 工作的不协调&#xff1a;开发人员在开发阶段&#xff0c;测试和运维人员其实是处于等待…

什么是依概率收敛

定义 设 X 1 , X 2 , . . . , X n , . . . X_1,X_2,...,X_n,... X1​,X2​,...,Xn​,... 是一个随机变量序列&#xff0c; A A A 是一个常数&#xff0c;如果对任意 ϵ > 0 \epsilon>0 ϵ>0&#xff0c;有 lim ⁡ n → ∞ P { ∣ X n − A ∣ < ϵ } 1 \lim_{n\…

SmartSoftHelp8,文件/文件夹,Web服务器IIS文件安全设置工具

工作文件&#xff0c;文件夹 web服务器 iis 文件&#xff0c;文件夹安全设置 用户&#xff1a; administrator user guest everyone 权限&#xff1a; 完全控制&#xff08;读、写&#xff09; 只读 读取 写入 修改 读取和执行 下载地址&#xff1a; https://p…

WPF绘图---Canvas中Polygon屏幕居中显示

问题描述 在一个Canvas中绘制了多个Polygon&#xff0c;由于坐标可能超出界面显示范围&#xff0c;需要将绘制的Polygon居中显示&#xff0c;并且缩放至界面大小&#xff0c;效果如下&#xff1a; xaml代码 <Borderx:Name"border"Background"#fff"Cli…

WebGL笔记:矩阵旋转运算的原理和实现

矩阵 矩阵&#xff08;Matrix&#xff09;是一个按照矩形纵横排列的复数集合 矩阵就像一个矩形的阵盘&#xff0c;通过其中纵横排列的元素我们可以摆出不同功能的阵法&#xff0c;比如位移矩阵、旋转矩阵、缩放矩阵 …在矩阵中的每一行&#xff0c;或者每一列数字构成的集合&a…