网站服务器和空间的区别,新闻 最新消息,wordpress美金,鲜花网站建设介绍#x1f30e; C11异步futrue 文章目录#xff1a;
C11异步futrue future介绍 应用场景 future操作 std::async函数模版 std::packaged_task类模版 std::promise类模版 #x1f680;future介绍 std::future是C11标准库… C11异步futrue 文章目录
C11异步futrue future介绍 应用场景 future操作 std::async函数模版 std::packaged_task类模版 std::promise类模版 future介绍 std::future是C11标准库中的⼀个模板类它表⽰⼀个异步操作的结果。当我们在多线程编程中使⽤异步任务时std::future可以帮助我们在需要的时候获取任务的执⾏结果。std::future的⼀个重要特性是能够阻塞当前线程直到异步操作完成从⽽确保我们在获取结果时不会遇到未完成的操作。 应用场景
异步任务 当我们需要在后台执⾏⼀些耗时操作时如⽹络请求或计算密集型任务等std::future可以⽤来表⽰这些异步任务的结果。通过将任务与主线程分离我们可以实现任务的并⾏处理从⽽提⾼程序的执⾏效率。并发控制 在多线程编程中我们可能需要等待某些任务完成后才能继续执⾏其他操作。通过使⽤std::future我们可以实现线程之间的同步确保任务完成后再获取结果并继续执⾏后续操作。结果获取std::future提供了⼀种安全的⽅式来获取异步任务的结果。我们可以使⽤std::future::get()函数来获取任务的结果此函数会阻塞当前线程直到异步操作完成。这样在调⽤get()函数时我们可以确保已经获取到了所需的结果。 future操作 一个main thread可以顺序执行多个IO操作但是执行IO操作是非常耗费时间的而我们又恰好只是想要IO操作的结果所以main thread就可以通过创建child thread来执行IO再通过future来获取IO结果 std::future本质上不是一个异步任务而是一个辅助我们获取异步任务结果的东西。 std::future并不能单独使用必须搭配一些能够执行异步任务的模版类或函数一起使用异步任务使用搭配
std::async函数模版异步执行一个函数返回函数对象获取函数执行结果。std::packaged_task类模版为一个函数生成一个异步任务对象可调用对象用于在其他线程中执行。std::promise类模版实例化的对象可以返回一个future在其他线程中向promise对象设置数据其他线程的关联future就可以获取数据。 std::async函数模版 std::async是⼀种 将任务与std::future关联 的简单⽅法。它创建并运⾏⼀个异步任务并返回⼀个与该任务结果关联的std::future对象。默认情况下std::async是否启动⼀个新线程或者在等待future时任务是否同步运⾏都取决于你给的 参数。这个参数为std::launch类型
std::launch::deferred表明该函数会被延迟调⽤直到在future上调⽤get()或者wait()才会开始执⾏任务。std::launch::async 表明函数会在⾃⼰创建的线程上运⾏。std::launch::deferred | std::launch::async 内部通过系统等条件⾃动选择策略。
#include iostream
#include futureint Add(int num1, int num2)
{std::cout into Add()! std::endl;return num1 num2;
}int main()
{// std::launch::async策略内部创建一个线程执行函数函数运行结果通过future获取// std::launch::deferred策略同步策略获取结果的时候再去执行任务// std::futureint res std::async(std::launch::async, Add, 11, 22);// 进行了一个异步非阻塞调用调用后直接执行std::futureint res std::async(std::launch::deferred, Add, 11, 22);// 进行同步调用调用后等待wait或get才会执行std::this_thread::sleep_for(std::chrono::seconds(1));std::cout —————————————————————————————————— std::endl;// std::futureint::get() : 用于获取异步任务的结果如果还没有结果就会阻塞std::cout res.get() std::endl;return 0;
}std::packaged_task类模版 std::packaged_task就是将任务和 std::feature 绑定在⼀起的模板是⼀种对任务的封装。我们可以通过std::packaged_task对象获取任务相关联的std::feature对象通过调⽤ get_future() 方法获得。std::packaged_task的模板参数是函数签名。可以把std::future和std::async看成是分开的⽽ std::packaged_task则是⼀个整体。 std::async是一个模版函数内部会创建线程执行异步任务而std::packaged_task是一个模版类一个任务包是对一个函数进行二次封装封装成为一个可调用对象作为任务放到其他线程执行的。任务包封装好了以后可以在任意位置进行调用通过关联的future来获取执行结果。 #include iostream
#include future
#include threadint Add(int num1, int num2)
{std::cout into Add()! std::endl;return num1 num2;
}int main()
{// 1. 封装任务std::packaged_taskint(int, int) task(Add);// 封装成task任务包// 2. 获取任务包关联的future对象std::futureint res task.get_future();// 2. 执行任务task(11, 22);// 3. 获取结果std::cout res.get() std::endl;return 0;
}这是在main thread中执行task但是我们想要的是可以异步执行任务所以创建一个线程来进行异步执行任务。 尽量不要把任务函数当成线程的入口函数这样每次执行任务创建线程任务结束线程也会销毁如果任务过于调用频繁会导致线程不断的创建销毁。比较好的方式是把任务放在线程池当中让去不断的执行任务。 创建线程以匿名函数作为线程的入口函数内部再调用task任务包单但是lambda表达式不能直接传task调用拷贝构造。 因为std::packaged_task不允许拷贝构造所以我们可以通过传递指针的方式防止拷贝构造发生。同时task如果在不同作用域需要考虑作用域的问题(res获取不到get_future)不能直接传裸的指针可以通过智能指针进行管理并传参。
#include iostream
#include future
#include thread
#include memoryint Add(int num1, int num2)
{std::cout into Add()! std::endl;return num1 num2;
}int main()
{// 1. 封装任务auto task std::make_sharedstd::packaged_taskint(int, int)(Add);// 封装成task任务包, 创建智能指针进行管理// 2. 获取任务包关联的future对象std::futureint res task-get_future();std::thread trd([task](){ // 匿名函数作为线程入口函数让线程来执行封装后的任务(*task)(11, 22);});// 3. 获取结果std::cout res.get() std::endl;trd.join();return 0;
}std::promise类模版 std::promise提供了⼀种设置值的⽅式它可以在设置之后通过相关联的std::future对象进⾏读取。换种说法就是之前说过std::future可以读取⼀个异步函数的返回值 但是要等待就绪 ⽽std::promise就提供⼀种方式⼿动让 std::future就绪。
std::promise是一个模版类是对于结果的封装
在使用的时候先实例化一个指定结果的primise对象。通过promise对象获取关联的future对象。在任意位置给promise设置数据就可以通过关联的future获取到这个设置的数据。
#include iostream
#include thread
#include future
#include memoryint Add(int num1, int num2)
{std::cout into Add()! std::endl;return num1 num2;
}int main()
{// 1. 在使用的时候先实例化一个指定结果的primise对象。std::promiseint pro;// 2. 通过promise对象获取关联的future对象。std::futureint ret pro.get_future();// 3. 在任意位置给promise设置数据就可以通过关联的future获取到这个设置的数据。std::thread td([pro](){int sum Add(11, 22);pro.set_value(sum);});std::cout ret.get() std::endl;td.join();return 0;
}同理依旧需要对不同作用域进行考虑所以使用智能指针还是比较安全的这里就不再赘述。