c++11 std::thread和mutex用法

news2024/9/25 10:40:39

c++11 std::thread和mutex用法

  • thread和mutex用法
    • thread简单示例
    • thread构造函数梳理
    • thread关键成员函数
    • mutex使用

thread和mutex用法

本文对c++ 11中的std::thread 和 mutex作简要的使用说明

thread简单示例

#include <iostream>
#include <string>
#include <thread>
using namespace std;


void thread_hello_wolrd()
{
	cout << "hello world!" << endl;
}

void thread_any_word(string&str)
{
	cout << str << endl;
}
int main()
{
	thread t_hello(thread_hello_wolrd);
	t_hello.join(); //等待t_hello子线程结束,才继续下面的操作

	string str = "hello my world!";
	thread t_any_word(thread_any_word, std::ref(str));
	t_any_word.detach(); //t_any_world子线程与主线程分离,即使主线程结束,也会运行

	return 0;
}

thread构造函数梳理

thread() _NOEXCEPT:默认构造函数,创建的是空thread对象
explicit thread(_Fn&& _Fx, _Args&&… _Ax):可变参数的构造函数,该线程是可jointable的
thread(const thread&) = delete;拷贝构造函数不可用
thread(thread&& _Other) _NOEXCEPT:移动构造函数,使用之后,other线程为空,移交给当前thread

#include <iostream>
#include <thread>
#include <chrono>

using namespace std;

void fun1(int n)
{
	for (int i = 0; i < 10; i++)
	{
		cout << "fun1:" << n << endl;
		this_thread::sleep_for(chrono::microseconds(10));
	}
}

void fun2(int& n)
{
	for (int i = 0; i < 10; i++)
	{
		cout << "fun2:" << n << endl;
		++n;
		this_thread::sleep_for(chrono::microseconds(10));
	}
}

int main()
{
	int n = 0; 
	thread t1;
	thread t2(fun1, n);
	thread t3(fun2, std::ref(n));
	thread t4(move(t3));  //t3线程为空
	t2.join();
	t4.join();
	cout << "result n =" << n << endl;

	return 0;
}

在这里插入图片描述

thread关键成员函数

  • get_id():获取线程id
  • joinable(): 判断线程是否可joinable()
    joinable()函数是一个布尔类型的函数,他会返回一个布尔值来表示当前的线程是否是可执行线程(能被join或者detach),因为相同的线程不能join两次,也不能join完再detach,同理也不能detach,所以joinable函数就是用来判断当前这个线程是否可以joinable的。通常不能被joinable有以下几种情况:
    1)由thread的缺省构造函数而造成的(thread()没有参数:
    2)该thread被move过(包括move构造和move赋值):
    3)该线程被join或者detach过。
  • detach(): 将当前线程脱离主线程,线程可以单独执行
  • swap(): 交换两线程的句柄
  • std::this_thread::getid():获取当前线程id
  • std::this_thread::yield(): 当前线程放弃执行,调度另一线程继续执行
  • sleep_until(): 线程休眠至某时刻被唤醒
  • sleep_for(): 线程休眠时间片后被唤醒

mutex使用

多个线程访问共享资源时,需要加锁互斥访问

  • 独占式互斥量:std::mutex独占工互斥量加解锁是成对的,同一个线程内独占式互斥量在没有解锁的情况下,再次对其加锁是不正确的。
  • 递归式互斥量:std::recursive_mutex 递归式互斥量是在同一个线程内互斥量没有解锁的情况下可以再次对其加锁,但其加解锁的次数需要保持一致。
  • 允许超时的独占式互斥量: std::time_mutex
  • 允许超时的递归式互斥量: std::recursive_time_mutex
#include<iostream>
#include <thread>
#include <mutex>

using namespace std;

int total_num = 0;
std::mutex mtx;

void fun1()
{
	
	for (int i = 0; i < 500; i++)
	{ 
		mtx.lock();                      //对异常抛出的情况,会发生死锁
		cout << "fun1:" << total_num++ << endl;
		mtx.unlock();
		this_thread::sleep_for(chrono::microseconds(10));
	}
	
}

void fun2()
{
	
	for (int i = 0; i < 500; i++)
	{
		{
			std::lock_guard<mutex>gd(mtx); //可以防止死锁,更安全,作用域有效
			cout << "fun2:" << total_num++ << endl;
		}
		this_thread::sleep_for(chrono::microseconds(10));
	}
	
}

int main()
{
	std::thread t1(fun1);
	std::thread t2(fun2);
	t1.join();
	t2.join();
	return 0;
}

若线程1对共享资源的访问时间过长,而线程2又不想等那么久,可以设定一个超时时间 ,在超时时间内若线程1中的互斥量还没有解锁,线程2就继续向下执行,这就是允许超时的互斥量。lock_guard只是提供了对互斥量最基本的加解锁封装,而unique_lock提供了多种构造方法,使用起来更加灵活,对于允许超时的互斥量需要使用unnique_lock来包装。

#include <iostream>
#include <thread>
#include <mutex>
#include <Windows.h>

using namespace std;

timed_mutex mtx;
void fun1()
{
    unique_lock<timed_mutex> t1(mtx);
    Sleep(2000); //模拟其他事项占用了大量时间
    cout << "fun1" << endl;
}

void fun2()
{
    unique_lock<timed_mutex> t1(mtx, chrono::milliseconds(1000));//设置超时时间为1秒
    cout << "fun2" << endl;
}

int main(int argc, char* argv[])
{
    thread t1(fun1);
    Sleep(100);   //让线程1先启动
    thread t2(fun2);
    t1.join();
    t2.join();

    return 0;
} 

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

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

相关文章

mysql性能监控

一.使用show profile查询剖析工具&#xff0c;查看mysql语句执行时间&#xff1a; 官网&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/show-profile.html mysql -uroot -p //进入数据库服务器 use 数据库名 //进入数据库 set profiling1; //开启profiling参数 select…

Python基础(十二):字典的详细讲解

文章目录 字典的详细讲解 一、字典的应用场景 二、创建字典的语法

具身智能综述和应用(Embodied AI)

什么是具身智能&#xff1f; 目前人工智能的进展&#xff0c;在诸多数据源和数据集&#xff08;Youtube、Flickr、Facebook&#xff09;、机器计算能力&#xff08;CPU、GPU、TPU&#xff09;的加持下&#xff0c;已经在CV、NLP上取得了许多任务&#xff08;如目标检测、语义分…

Python学习----闭包和装饰器

情景&#xff1a; 当我们调用函数的时候&#xff0c;函数调用完成之后&#xff0c;函数内定义的变量都会被销毁&#xff0c;但是我们有时候需要保存函数内的这个变量&#xff0c;每次在这个变量的基础上完成一系列的操作&#xff0c;比如&#xff1a;每次在这个变量的基础上和其…

【全网惟一面向软件测试人员的Python基础教程】- 学Python之前要搞懂的道理

全网惟一面向软件测试人员的Python基础教程 起点&#xff1a;《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 文章目录全网惟一面向软件测试人员的Python基础教程计算机的本质是什么&#xff1f;什么是编程呢&#x…

Java泛型的使用和原理

文章目录泛型-概述基础使用泛型类的使用泛型类派生子类泛型接口泛型方法类型通配符类型通配符上限类型通配符下限常用泛型标识符类型擦除使用注意泛型与数组泛型和反射其他泛型-概述 Java 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性&#xff0c;泛型提…

第十四届蓝桥杯集训——JavaC组第八篇——进制转换

第十四届蓝桥杯集训——JavaC组第八篇——进制转换 目录 第十四届蓝桥杯集训——JavaC组第八篇——进制转换 短除法 十进制转二进制示例&#xff1a; 十进制转换二进制 十进制转换八进制 十进制转换十六进制 二进制转十进制 八进制转十进制 十六进制转十进制 进制转换…

【✨十五天搞定电工基础】半导体器件

本章要求1. 理解PN结的单向导电性&#xff0c;三极管的电流分配和电流放大作用 2. 了解二极管、稳压管和三极管的基本构造、工作原理和特性曲线&#xff0c;理解主要参数的意义 3. 会分析含有二极管的电路 目录 一、半导体基础知识 1、本征半导体的导电机理 2、杂质半导体 …

部分核心技术(持续更新)

文章目录1.Schedule&#xff08;定时任务&#xff09;2.高并发线程安全的解决方案2.1为什么不适用同步锁&#xff08;Synchronized&#xff09;&#xff1f;2.2 Redis的分布式锁setnx2.3 redisson分布式锁&#xff08;看门狗机制&#xff09;2.3.1 Redis的分布式锁setnx产生的问…

保姆级入门nest笔记

使用 NEXT 搭建后台服务接口 https://docs.nestjs.com/ # 准备工作 安装 node 全局安装 nest npm i -给nestjs/cli nest --version # 创建项目 创建项目next new 启动项目npm run start 或 npm run start:dev 访问接口 localhost:3000 获取命令解释 next g -h # 快速创建…

Pixracer接线图 及电调调参 BLheliSuite

Pixracer接线指南 pixracer官方链接 正反面引脚定义 接口含义 BLheliSuite调参软件 官方下载&#xff1a; https://www.mediafire.com/folder/dx6kfaasyo24l/BLHeliSuite 我使用了如下软件https://www.mediafire.com/file/9uccf1zy3wqb1w5/BLHeliSuite32_32.9.0.3.zip/fil…

Bio-Net:编解码器结构的循环双向连接网络

目录 摘要 方法 循环双向跳跃连接 前向跳跃连接 后向跳跃连接 递归的推断训练 BiO-Net网络结构 总结 摘要 对UNet以前的扩展主要集中对现有模块的改进或者提出新的模块来提高性能。因此这些变量通常会导致模型的复杂性不可忽视的增加。为了解决这种复杂性的问题。在本…

redis cluster 集群安装

redis cluster 集群安装 redis集群方案 哨兵集群 如图&#xff0c;实际上还是一个节点对外提供服务&#xff0c;所以虽然是三台机器&#xff0c;但是还是一台机器的并发量&#xff0c;而且master挂了之后&#xff0c;整个集群不能对外提供服务 cluster集群 多个主从集群节点…

五、伊森商城 前端基础-Vue 整合ElementUI快速开发 p28

目录 一、安装 1、安装ElementUI 2、在main.js文件中引入 2.1、引入ElementUI组件 2.2、让Vue使用ElementUI组件 二、使用 1、在hello.vue组件使用单选框 2、使用ElementUI快速搭建后台管理系统 2.1、修改App.vue 3、修改功能成动态显示 3.1、编写快速生成组件的模板 3…

java计算机毕业设计ssm学习互助平台网站8f554(附源码、数据库)

java计算机毕业设计ssm学习互助平台网站8f554&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…

C++11之引用

文章目录目的为啥要引入右值引用什么是右值引用右值引用作用移动构造函数移动语义 std::move移动语义注意事项完美转发博客目的 了解对应左值引用&#xff0c; 右值引用&#xff0c;移动语义&#xff0c; 完美转发含义。 右值引用&#xff08;及其支持的移动语义Move semanti…

1562_AURIX_TC275_电源监控

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 这一次的学习笔记内容比较少&#xff0c;因为有几页的文档内容跟之前看过的DataSheet内容雷同。因此&#xff0c;相应的学习笔记不再整理。 之前的学习笔记&#xff1a; (56条消息) 1451_…

Python学习基础笔记四十——os模块

os模块是与操作系统交互的一个接口。 os的方法Linux命令备注os.getcwd()pwd获取当前工作目录路径os.chdir()cd切换当前工作目录os.makedirs(dirname1/dirname2)mkdir -p dirname1/dirname2生成多级目录os.removedirs(dirname1)rmdir删除多级目录os.mkdir(dirname)mkdir dirnam…

JAVA入门零基础小白教程day04-数组

day04_java基础 课程目标 1. 【掌握】 IDEA的基本使用 2. 【理解】 什么是数组 3. 【掌握】 数组的定义及初始化 4. 【理解】 数组的内存图 6. 【理解】 数组常见的问题 7. 【掌握】 数组的案例 8. 【理解】 二维数组开发工具 一维数组 什么是数组 数组就是存储数据长度固定…

【Linux】源码安装Apache、Mysql、PHP以及LAMP部署验证

文章目录源码安装相关理论源代码安装特点源码包安装步骤一、源码安装Apache1、编译安装依赖包 apr2、编译安装依赖包 apr-util3、编译安装依赖包 pcre4、编译安装 Apache5、重启 apache 服务6、修改网页显示内容7、访问测试二、源码安装Mysql1、把系统自带的 boost 库卸载&…