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

线程调用类方法:

有参数时调用方法:

当参数为引用时:

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

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

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

lock_guard<类型> 变量名(锁变量);
作用,为防止死锁发生,它可以进行锁的自动加锁和解锁

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

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

必须手动锁定

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

std::adopt_lock只是用于接管之前的锁mtx,所以在这一行之前需要对mtx进行lock才会真正的被lock
#include
用于主线程,子线程按次序执行

如果需要线程一个一个执行,则可以这样写
- #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;
- }


nofity_one()只会随机唤醒其中运行的一个线程
call_once(once_flag, this_thread::get_id());
头文件: #include "mutex"
作用:线程只能调用该方法一次


只调用了一次

主线程没有限制

如何在join前就获取最终num的结果?
promise future
头文件:#include "future"

自定义启动线程函数:
头文件#include "future"
packaged_task<函数类型> 变量名(函数名);

主要是能与promise、future搭配使用
async
头文件#include "future"



fvalue.get()过后才会进行函数调用
原子操作
允许无所并发编程,涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的,原子对象不具有数据竞争
头文件:#include "atomic"
锁是在牺牲性能的情况下进行对操作的细致管控,这个时候就用原子变量
不加锁:

加锁:


原子操作:


C++11 多线程std:: async与std::thread的区别_c++11 thread asy-CSDN博客
- // 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));
- }
-

- // 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));
- }
-

- // 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
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
guardLock(mtx) ; - std::this_thread::sleep_for(std::chrono::milliseconds(10));
- UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
- value--;
- }
- UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
- }

会一增一减
- // 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
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
guardLock(mtx) ; - std::this_thread::sleep_for(std::chrono::milliseconds(10));
- UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
- value--;
- }
- UKismetSystemLibrary::PrintString(this, FString::FromInt(value));
- }

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));
- }

- 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));
- }

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暂时没找到打印的办法,但是能够编过断点也有对应效果