日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人

并發(fā)編程一般指多線程編程,C++11之后關(guān)于多線程編程有幾個(gè)高級(jí)API:

  • std::thread

  • std::future

  • std::shared_future

  • std::promise

  • std::packaged_task

  • std::async

可能很多人都搞不清楚它們之前有什么聯(lián)系,可以直接看這張圖:

如果連它們是什么都不知道的朋友,可以先看看這個(gè):https://mp.weixin.qq.com/s/rPjRTOTYK2SGr6WxgWI_Vg


從這張圖我們可以大體看出來(lái):

  • packaged_task ≈ promise + function

  • async ≈ thread + packaged_task

  • 通過(guò)promise的get_future()可拿到future

  • 通過(guò)future的share()可拿到shared_future


promise和future是線程之間的同步通道,類(lèi)似于條件變量的封裝,看它的使用:

#include
#include
#include

int main() {
 std::promiseprom;
 std::futuref = prom.get_future();
 prom.set_value(true);
 std::cout << f.get() << std::endl;
}


首先創(chuàng)建一個(gè)promise,通過(guò)promise可以拿到future,future有wait()和get()等方法,這種方法會(huì)阻塞當(dāng)前線程,直到future的源promise調(diào)用了set_value,future的wait()只有阻塞功能,而get()方法不僅有阻塞功能,還能拿到set_value()設(shè)置的值。我舉個(gè)多線程的示例:


#include
#include
#include

int main() {
 std::promiseprom;
 auto f = prom.get_future();
 std::thread t(
 [](std::promisep) {
 std::this_thread::sleep_for(std::chrono::seconds(2));
 p.set_value(100);
 },
 std::move(prom));
 std::cout << f.get() << std::endl;
 if (t.joinable()) t.join();
}


這段代碼執(zhí)行后會(huì)在兩秒后輸出100。這個(gè)結(jié)果就驗(yàn)證了上面啰嗦的promise的future的get()的阻塞和獲取結(jié)果的能力。


注意:一個(gè)promise的set_value()只能調(diào)用一次,如果調(diào)用多次,就會(huì)throw exception,如果外部沒(méi)catch exception,程序就會(huì)crash。


promise的阻塞功能還是蠻好用的,我在工程中就經(jīng)常用到它。


介紹完promise,再來(lái)看看packaged_task

#include
#include
#include
int main() {
 std::packaged_task task([](int a, int b) { return a + b; });
 auto f = task.get_future();
 std::thread t(std::move(task), 1, 2);
 std::cout << f.get() << std::endl;
 if (t.joinable()) t.join();
}


可以拿這段代碼和上面那段promise的代碼對(duì)比看看,可以得出結(jié)論:

packaged_task ≈ promise + function

promise只能set_value,不太好執(zhí)行復(fù)雜的邏輯,有執(zhí)行函數(shù)+阻塞的需求時(shí),就可以考慮使用packaged_task。

可以思考一下,如果要你封裝一個(gè)packaged_task,你會(huì)怎么做?


再看async:

#include
#include
#include
int main() {
 auto f = std::async(
 std::launch::async, [](int a, int b) { return a + b; }, 1, 2);
 std::cout << f.get() << std::endl;
}

這里可以看到,使用了async后,連thread都不需要?jiǎng)?chuàng)建了,這也就驗(yàn)證了上面圖中的結(jié)論:

async ≈ thread + packaged_task


這里請(qǐng)注意:async中的第一個(gè)參數(shù)我使用的是std::launch::async,只有當(dāng)參數(shù)為std::launch::async時(shí),函數(shù)才會(huì)異步執(zhí)行。

參數(shù)還可以是std::launch::deferred,參數(shù)為這個(gè)時(shí),函數(shù)不會(huì)異步執(zhí)行,只有當(dāng)對(duì)應(yīng)的future調(diào)用了get時(shí),函數(shù)才會(huì)執(zhí)行,而且是在當(dāng)前線程執(zhí)行。

關(guān)于async有幾個(gè)坑,我之前寫(xiě)過(guò)一篇文章,可以看這個(gè):async的兩個(gè)坑


介紹完async,再介紹下shared_future

普通的future有個(gè)特點(diǎn),它不能拷貝,只能移動(dòng),這就意味著只能有一個(gè)線程一個(gè)實(shí)例可以通過(guò)get()拿到對(duì)應(yīng)的結(jié)果。

如果想要多個(gè)線程多個(gè)實(shí)例拿到結(jié)果,就可以使用shared_future,那怎么拿到shared_future,可以通過(guò)普通future的shared()方法。

#include
#include
#include
int main() {
 std::promiseprom;
 auto fu = prom.get_future();
 auto shared_fu = fu.share();
 auto f1 = std::async(std::launch::async, [shared_fu]() { std::cout << shared_fu.get() << std::endl; });
 auto f2 = std::async(std::launch::async, [shared_fu]() { std::cout << shared_fu.get() << std::endl; });
 prom.set_value(102);
 f1.get();
 f2.get();
}

看到這里,大家應(yīng)該明白thread、future、promise、packaged_task、async之間的關(guān)系了吧。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉