std::thread
头文件引入#include <thread>,创建线程thread th1(func);,主要了解一下两个函数;
join():可以调整阻塞态位置,个人理解,如果创建了线程,立马用join纯属脱裤子那啥,和直接调用函数没区别,主线程照样阻塞,阻塞主线程,等待子线程结束后再结束,不执行后续程序。
detach():主线程为主,将子线程和主线程的关联分离,管你线程在干嘛,主线程结束下班休息。
std::lock_guard、std::unique_lock
资源获取及初始化(RAII),lock_guard是个模板类,会在构造函数中初始化信号量,会在析构函数中解锁资源,避免死锁情况。使用方法为lock_guard<mutex> lock(信号量)
unique_lock和前者使用方法相同,同属模板类,区别为:前者不够灵活,创建的对象只有超出作用域时,对象被析构才能释放这个锁;后者又更多的函数供使用,可以提前对锁进行操作;
std::mutex
互斥量,头文件引用#inclcude <mutex>,mutex m;然后使用lock和unlock函数来上锁和解锁,通过上锁和解锁来避免和解决多线程不安全的问题。
原子操作
有文件引入#include <atomic>,可以理解为信号量和锁的封装使用,可以自动帮我们完成一些上锁和解锁的操作。
条件变量
头文件#include <condition_variable>,定义为condition_variable cv;常用的是 wait()和notify_one()两个成员函数,前者是等待,生效后将阻塞线程进行,等待被后者这个函数唤醒,notify_one()是唤醒其中一个wait(),与之相对应的还有notify_all() 可以唤醒所有等待线程。
信号量
这个是在c++20之后才支持的,要注意编译器版本,头文件引入#include <semaphore>,常用模板类counting_semaphore(初始化需要赋初值counting_semaphore<5> cs(0);其中5是我自己瞎写的表示一次可以被唤醒的线程个数上限。)的模板特化为binary_semaphore(counting_semaphore上限为1的情况) 其中常用的成员函数有release和acquire 。
a. semaphore release == condition_variable notify
b. semaphore acquire == condition_variable wait
本文详细介绍了C++中的多线程技术,包括std::thread的使用,join()和detach()的区别,以及互斥量std::mutex、锁管理如std::lock_guard和std::unique_lock的作用。此外,还探讨了原子操作、条件变量和信号量在并发编程中的应用,为理解和实现高效的多线程程序提供了基础。
4973





