文章目录
(一) 线程概念、创建及传参
(二) 独占互斥锁–mutex,lock_guardy与其他mutex
(三) unique_lock替换lock_guardy
(四) 单例模式(Singleton)下的线程安全问题
(五) window临界区
(六) condition_variable条件变量
(七) std::async异步任务与std::future< >
(八) packaged_task< >与promise< >
(九) 原子操作atomic<>简介
(1)简介
std::async一般与std::future< >配套使用,前者异步或同步调用一个函数,返回一个future的模板类对象,在future中可以拿到入口函数的返回值
(2)std::async
1.async异步调用函数,即创建一个线程,返回一个future模板类
2.async使用方式同thread 也可传入类函数(记住前面加&)
3.第一参数可以传入 std::launch::deferred标记,即延迟调用,等到get()才调用,且不创建线程,直接在主线程中执行(id一样),若不调用get或wait则不执行
4.不传入则默认是 std::launch::async | std::launch::deferred,则可能同步或异步
5.std::launch::async强制异步任务创建新线程,若系统资源紧张则通过thread创建失败导致崩溃
6.传入位或 (即同4)相当于开启两个标志位,是否开启线程或延迟由系统判定
- 使用方法
- 简单的异步调用函数,参数传入方法同thread创建,一般会创建线程执行,使用future获取返回结果
- get()获取结果若异步调用未结束则堵塞主线程
- 若不调用get主线程结束,异步任务未结束则主线程结束后等待,可能出现问题
int mythreadfuntion(int num)
{
cout << "mythreadfuntion异步执行 thread_id =" << this_thread::get_id() << endl;
std::chrono::milliseconds time(3000); //三秒钟
std::this_thread::sleep_for(time); //线程休眠
cout << "mythreadfuntion结束执行 thread_id =" << this_thread::get_id() << endl;
return num * 10;
}
std::future<int> result = std::async(mythreadfuntion,6); //创建一个线程开始执行返回值为int的参数传入6的mythreadfuntion
std::cout << "main主函数继续执行 " << endl; //不会堵塞主函数
std::cout << "async获取结果: result.get = " << async_result.get() << endl; //获取结果,若函数还没执行结束则堵塞
- 传入参数std::launch::deferred
- 以上使用方法不传入第一参数,若第一参数传入std::launch::deferred则表示延迟执行,即不创建线程,直到执行到future的get函数才开始执行,且在主线程中执行
std::future<int> async_result = std::async(std::launch::deferred,mythreadfuntion, 6); //直接在主线程中执行(id一样),若不调用get或wait则不执行
std::cout << "main主函数继续执行 " << endl;
//result.wait(); //调用也会wait堵塞
std::cout << "async获取结果: result.get = " << async_result.get() << endl; //到此才调用mythreadfuntion
- 传入参数std::launch::async
- 效果同1
-
async与thread区别
thread强制创建新线程,若资源紧张则创建失败 thread不方便获取入口函数的返回值,可使用全局函数或 packaged_task获取 async创建异步任务,有系统判定是否可用创建线程,若不可以则在当前调用线程执行 async若延迟任务,线程中没有使用get或wait则不调用入口函数 async可用使用future.wait_for(3s)对任务状态进行判断 async可用future对入口函数返回值进行获取 线程数量最好控制在100-200
(3)std::future< >
1.用于访问异步数据,即将来的数据
2.调用get()或wait()则等待子线程执行完才返回
3.不能多次调用get(),只能调用一次,除非用future_share
4.调用wait_for返回一个包含 超时,延迟,就绪三种枚举类型std::future_status
5.若async传入deferred,wait_for传入时间无效,程序不会等待,进入次调用get才执行函数
6.std::chrono::seconds(1)传入wait_for等待时长
7.vaile()返回一个布尔值,判定里面是否存在有效值
- wait_for的使用
- 传入参数是std::chrono::seconds(int)时间(或 1s),返回值是枚举类型std::future_status,包含超时,就绪,延迟三种状态,用来判断async线程调用的状态
- 超时则线程为执行结束
- 就绪即可获取函数返回值
- 延迟则延迟执行,此时可调用get()让其执行后返回
std::future<int> result = std::async(mythreadfuntion, 6); //创建一个线程开始执行
std::cout << "main主函数继续执行 " << endl;
std::future_status s = result.wait_for(std::chrono::seconds(1)); //返回一个枚举类型enum
if(s == future_status::timeout) //wait_for 1秒时超时
std::cout << "wait_for等待超时 " << endl;
else if(s == future_status::ready) //wait_for 4秒时准备
std::cout << "wait_for准备就绪" << endl;
else if (s == future_status::deferred) //async传入deferred且程序不会等待,进入次调用get才执行函数
std::cout << "wait_for延迟" << endl;
(4)std::share_future< >
1.future由于get()不是复制赋值,而是值的移动,所以只能调用一次,调用后则已被清空
2.使用future创建shared_future两种方式
一种std::shared_future result_s (std::move(result));
另一种std::shared_future result_s (result.share());
3.用get()获取值,可以调用多次
std::shared_future<int> result_s;
if(result.valid()) //判断是否有有效值
result_s = result.share(); //创建共享
std::cout << "async获取结果: result_s.get = " << result_s.get() << result_s.get() << endl; //调用get则堵塞,若注释此句主函数将继续执行,但不会退出(可能不安全)
- 测试代码
#include <iostream>
#include<thread>
#include<mutex>
#include <future>
using namespace std;
int mythreadfuntion(int num)
{
cout << "mythreadfuntion异步执行 thread_id =" << this_thread::get_id() << endl;
std::chrono::milliseconds time(3000); //三秒钟
std::this_thread::sleep_for(time); //线程休眠
cout << "mythreadfuntion结束执行 thread_id =" << this_thread::get_id() << endl;
return num * 10;
}
int main()
{
std::cout << "main主函数id = " << this_thread::get_id() << endl;
std::future<int> result = std::async(mythreadfuntion, 6); //创建一个线程开始执行
std::cout << "main主函数继续执行 " << endl;
std::future_status s = result.wait_for(std::chrono::seconds(1)); //返回一个枚举类型enum
if(s == future_status::timeout) //wait_for 1秒时超时
std::cout << "wait_for等待超时 " << endl;
else if(s == future_status::ready) //wait_for 4秒时准备
std::cout << "wait_for准备就绪" << endl;
else if (s == future_status::deferred) //async传入deferred且程序不会等待,进入次调用get才执行函数
std::cout << "wait_for延迟" << endl;
std::shared_future<int> result_s;
if(result.valid()) //判断是否有有效值
result_s = result.share(); //创建共享
std::cout << "async获取结果: result_s.get = " << result_s.get() << result_s.get() << endl; //调用get则堵塞,若注释此句主函数将继续执行,但不会退出(可能不安全)
std::cout << "main主函数结束 " << endl;
}