C++ 多线程 学习笔记

这篇具有很好参考价值的文章主要介绍了C++ 多线程 学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ 多线程 学习笔记,学习,笔记

线程睡眠很稳定,但无线程睡眠不稳定

C++ 多线程 学习笔记,学习,笔记


线程调用类方法:

C++ 多线程 学习笔记,学习,笔记


有参数时调用方法:

C++ 多线程 学习笔记,学习,笔记


当参数为引用时:

C++ 多线程 学习笔记,学习,笔记


detach分离线程,分离线程与主线程同时进行,join会使主线程挂起,执行join进来的进程

C++ 多线程 学习笔记,学习,笔记

detach必须让主线程在还住运行的情况下调用,换句话说就是不能让detach的线程还没结束,主线程就结束,同时detach的函数传参不能是局部变量,换句话来说就是不能调用的函数还没结束,该变量就被销毁了

C++ 多线程 学习笔记,学习,笔记


当同一资源被多个线程同时引用时,为防止资源抢占,使用mutex,互斥锁

头文件#include "mutex"

C++ 多线程 学习笔记,学习,笔记


lock_guard<类型> 变量名(锁变量);

作用,为防止死锁发生,它可以进行锁的自动加锁和解锁

C++ 多线程 学习笔记,学习,笔记


unique_lock<类型> 变量名(锁名, 变参参数);

C++ 多线程 学习笔记,学习,笔记

延时加锁,直接这样定义数据会出现混乱

C++ 多线程 学习笔记,学习,笔记

必须手动锁定 

C++ 多线程 学习笔记,学习,笔记

直接用变参std::adopt_lock也会直接造成数据混乱 

C++ 多线程 学习笔记,学习,笔记

std::adopt_lock只是用于接管之前的锁mtx,所以在这一行之前需要对mtx进行lock才会真正的被lock


#include <condition_variable>

用于主线程,子线程按次序执行

C++ 多线程 学习笔记,学习,笔记

如果需要线程一个一个执行,则可以这样写

#include "iostream"
#include "chrono"
#include "thread"
#include "condition_variable"
#include "mutex"

using namespace std;

mutex mtx;
condition_variable cv;
bool sub_run = false;
int number = 0;

class A {
public:
	void add(int &b) {
		while (b < 10) {
			unique_lock<mutex> queLock(mtx);
			cv.wait(queLock, [&] { return !(number - 1); });
			b++; 
			cout << " add " << b << endl;
			this_thread::sleep_for(chrono::milliseconds(10));
			number = 2;
			cv.notify_all();
		}
	}
};

void Dec(int& c) {
	while (c < 10) {
		unique_lock<mutex> uniLock(mtx);
		cv.wait(uniLock, [&] { return !number; });
		c--;
		cout << " Dec " << c << endl;
		this_thread::sleep_for(chrono::milliseconds(10));
		number = 1;
		cv.notify_all();
	}
}

int main() {
	A a;
	int num = 5;
	thread th(&A::add, &a, ref(num));
	thread th1(Dec, ref(num));
	while (num < 10) {
		unique_lock<mutex> mainUniLock(mtx);
		cv.wait(mainUniLock, [&] { return !(number - 2); });
		num++;
		cout << " Main " << num << endl;
		this_thread::sleep_for(chrono::milliseconds(10));
		number = 0;
		cv.notify_all();
	}
	th.join();
	th1.join();
	cout << num << endl;

	return 0;
}

C++ 多线程 学习笔记,学习,笔记


C++ 多线程 学习笔记,学习,笔记

nofity_one()只会随机唤醒其中运行的一个线程


call_once(once_flag, this_thread::get_id());

头文件:  #include "mutex"

作用:线程只能调用该方法一次

C++ 多线程 学习笔记,学习,笔记

C++ 多线程 学习笔记,学习,笔记

只调用了一次

C++ 多线程 学习笔记,学习,笔记

主线程没有限制 


C++ 多线程 学习笔记,学习,笔记

如何在join前就获取最终num的结果?

promise     future

头文件:#include "future"

C++ 多线程 学习笔记,学习,笔记


自定义启动线程函数:

头文件#include "future"

packaged_task<函数类型> 变量名(函数名);

C++ 多线程 学习笔记,学习,笔记

主要是能与promise、future搭配使用


async

头文件#include "future"

C++ 多线程 学习笔记,学习,笔记

C++ 多线程 学习笔记,学习,笔记

C++ 多线程 学习笔记,学习,笔记

fvalue.get()过后才会进行函数调用


原子操作

允许无所并发编程,涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的,原子对象不具有数据竞争

头文件:#include "atomic"

锁是在牺牲性能的情况下进行对操作的细致管控,这个时候就用原子变量

不加锁:

C++ 多线程 学习笔记,学习,笔记

加锁:

C++ 多线程 学习笔记,学习,笔记

C++ 多线程 学习笔记,学习,笔记

原子操作:

C++ 多线程 学习笔记,学习,笔记

C++ 多线程 学习笔记,学习,笔记


C++11 多线程std:: async与std::thread的区别_c++11 thread asy-CSDN博客

参考:60 工具库-tuple_哔哩哔哩_bilibili


// Fill out your copyright notice in the Description page of Project Settings.


#include "TaskTest.h"
#include "chrono"
#include "Kismet/KismetSystemLibrary.h"
#include "mutex"
#include "thread"

// Sets default values
ATaskTest::ATaskTest()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void ATaskTest::BeginPlay()
{
	Super::BeginPlay();
	int a = 1;
	std::thread th(&ATaskTest::ThreadDo, this, std::ref(a));
	th.join();
	
}

// Called every frame
void ATaskTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

std::mutex mtx;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		mtx.lock();
		//std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
		mtx.unlock();
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记


// Fill out your copyright notice in the Description page of Project Settings.


#include "TaskTest.h"
#include "chrono"
#include "Kismet/KismetSystemLibrary.h"
#include "mutex"
#include "thread"

// Sets default values
ATaskTest::ATaskTest()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void ATaskTest::BeginPlay()
{
	Super::BeginPlay();
	std::thread th(&ATaskTest::ThreadDo, this, std::ref(a));
	th.detach();
}

// Called every frame
void ATaskTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

std::mutex mtx;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		mtx.lock();
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
		mtx.unlock();
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记


// Fill out your copyright notice in the Description page of Project Settings.


#include "TaskTest.h"
#include "chrono"
#include "Kismet/KismetSystemLibrary.h"
#include "mutex"
#include "thread"

// Sets default values
ATaskTest::ATaskTest()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

void ATaskTest::BeginPlay()
{
	Super::BeginPlay();
	std::thread th(&ATaskTest::ThreadDo, this, std::ref(a));
	std::thread th1(&ATaskTest::ThreadDo1, this, std::ref(a));
	th.detach();
	th1.detach();
}

std::mutex mtx;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		std::lock_guard<std::mutex> guardLock(mtx);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

void ATaskTest::ThreadDo1(int& value) {
	while (value < 10000) {
		std::lock_guard<std::mutex> guardLock(mtx);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value--;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记

会一增一减


// Fill out your copyright notice in the Description page of Project Settings.


#include "TaskTest.h"
#include "chrono"
#include "Kismet/KismetSystemLibrary.h"
#include "mutex"
#include "thread"

// Sets default values
ATaskTest::ATaskTest()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

void ATaskTest::BeginPlay()
{
	Super::BeginPlay();
	std::thread th(&ATaskTest::ThreadDo, this, std::ref(a));
	std::thread th1(&ATaskTest::ThreadDo1, this, std::ref(a));
	th.detach();
	th1.detach();
}

std::mutex mtx;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		std::unique_lock<std::mutex> uniLock(mtx, std::defer_lock);
		uniLock.lock();
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

void ATaskTest::ThreadDo1(int& value) {
	while (value < 10000) {
		std::lock_guard<std::mutex> guardLock(mtx);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value--;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记

unique_lock与lock_guard一样,在函数结束后会自动解锁,但unique_lock有更多操作,比如延迟加锁,接管锁,wait锁(wait不接受lock_guard)如果不需要这些操作还是lock_guard好一点,越多操作性能消耗也越高


std::mutex mtx;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		mtx.lock();
		std::unique_lock<std::mutex> uniLock(mtx, std::adopt_lock);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

void ATaskTest::ThreadDo1(int& value) {
	while (value < 10000) {
		std::lock_guard<std::mutex> guardLock(mtx);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value--;
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记


std::mutex mtx;
std::condition_variable cv;
bool isFirst = false;
void ATaskTest::ThreadDo(int& value) {
	while (value < 10000) {
		mtx.lock();
		std::unique_lock<std::mutex> uniLock(mtx, std::adopt_lock);
		cv.wait(uniLock, [=] {return !isFirst; });
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value++;
		isFirst = true;
		cv.notify_all();
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

void ATaskTest::ThreadDo1(int& value) {
	while (value < 10000) {
		std::unique_lock<std::mutex> guardLock(mtx);
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		cv.wait(guardLock, [=] {return isFirst; });
		UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
		value--;
		isFirst = false;
		cv.notify_all();
	}
	UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
}

C++ 多线程 学习笔记,学习,笔记

while内一个执行一次,使用std::condition_variable


std::atomic_int a(1);
void ATaskTest::ThreadDo() {
    while (a < 10000) {
        a++;
        //UKismetSystemLibrary::PrintString(this, FString::FromInt(a));
    }
}

void ATaskTest::ThreadDo1() {
    while (a < 10000) {
        a--;
        //UKismetSystemLibrary::PrintString(this, FString::FromInt(a));
    }
}

atomic_int暂时没找到打印的办法,但是能够编过断点也有对应效果文章来源地址https://www.toymoban.com/news/detail-703784.html

到了这里,关于C++ 多线程 学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++线程的简单学习及了解

    此篇文章只是线程的简单了解。 文章目录 前言 一、线程的优缺点 二、C++线程库 1.thread类的简单介绍 2.线程函数参数 总结 什么是线程? 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线

    2023年04月27日
    浏览(49)
  • C++系列十:日常学习-多线程

    目录 介绍: 理论: 比喻理解 案例: 生产者-消费者问题: C++ 是一种支持多线程编程的编程语言,它提供了丰富的多线程支持来充分利用现代多核处理器的性能。 C++ 多线程编程通常使用标准库中的 头文件以及其他相关的标准库组件来实现。 常用的类: std::thread:用于创建

    2024年02月10日
    浏览(33)
  • 多线程——学习笔记 1

    多线程的了解 什么是线程 线程是程序执行的一条路径, 一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率, 可以同时完成多项工作 多线程的应用场景 红蜘蛛同时共享屏幕给多个电脑 迅雷开启多条线程一起下载 QQ同时和多个人一起视频 服务器同时处理多个客

    2024年02月12日
    浏览(29)
  • (学习笔记-进程管理)线程

    在早期的操作系统都是以进程为独立运行的基本单位,直到后面,计算机科学家们提出了更小的能独立运行的基本单位: 线程   举个例子,假设要编写一个视频播放软件,那么软件功能的核心模块有三个: 从视频文件中读取数据 对读取的数据进行解压缩 把压缩后的视频数

    2024年02月14日
    浏览(35)
  • C++多线程学习(九、不安全的队列测试,简单封装线程安全队列)

    目录 不安全的队列测试 简单封装一个线程安全队列 下方是一个简单的程序,但是不安全: 由于代码中的线程t是在后台运行的,所以无法确定线程t是否已经完成了对myQ队列的操作,因此在主线程中处理myQ队列时,可能会出现竞争条件或者数据不一致的情况,导致输出的结果

    2024年02月13日
    浏览(30)
  • 线程的同步和互斥学习笔记

    目录 互斥锁的概念和使用  线程通信-互斥  互斥锁的创建和销毁  申请锁-pthread_mutex_lock  释放锁-pthread_mutex_unlock 读写锁的概念和使用 死锁的避免 线程通信-互斥 临界资源 一次只允许一个任务(进程、线程)访问的共享资源 概念:         不能同时访问的资源,比如写

    2024年01月25日
    浏览(33)
  • 【C++学习】线程库 | IO流 | 空间配置器

    🐱作者:一只大喵咪1201 🐱专栏:《C++学习》 🔥格言: 你只管努力,剩下的交给时间! 在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差。 C++11中最重要的特性就是支持了多线程编程,使得C++在并行编程

    2024年02月12日
    浏览(48)
  • C++多线程学习[四]:多线程的通信和同步、互斥锁、超时锁、共享锁

    初始化 (Init):该线程正在被创建。 就绪 (Ready):该线程在就绪列表中,等待CPU的调度。 运行 (Running):该线程正在运行。 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pend(锁、事件、信号量等阻塞)、suspend(主动pend)、delay(延时阻塞)、pendtime(因为锁、

    2024年01月16日
    浏览(32)
  • (学习笔记-进程管理)多线程冲突如何解决

    对于共享资源,如果没有上锁,在多线程的环境里,很有可能发生翻车。 在单核 CPU 系统里,为了实现多个程序同时运行的假象,操作系统通常以时间片调度的方式,让每个进程每次执行一个时间片,时间片用完了,就切换下一个进程运行,由于这个时间片的时间很短,于是

    2024年02月13日
    浏览(105)
  • 【学习笔记】Windows 下线程同步之互斥锁

    本文所涉及的同步主要描述在 Windows 环境下的机制,和 Linux 中的同步机制有一定的联系,但注意并不完全相同。类似于,Windows 和 Linux 按照自己的方式实现了操作系统中同步机制的概念 本文记录的是 Windows 下的互斥锁同步机制,但在 Windows 的同步机制中,其中很多的概念和

    2024年02月06日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包