中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

C++11線(xiàn)程異步-創(chuàng)新互聯(lián)

文章目錄
    • 1. 線(xiàn)程異步的概念
    • 2. future
      • 2.1 共享狀態(tài)
      • 2.2 常用成員函數(shù)
    • 3. promise
      • 3.1 常用成員函數(shù)
      • 3.2 promise的基本使用
    • 4. package_task
      • 4.1 常用成員函數(shù)
      • 4.2 package_task的基本使用
    • 5. async
      • 5.1 async的基本使用
    • 6. promise、package_task、async的對(duì)比與總結(jié)

創(chuàng)新互聯(lián)為企業(yè)級(jí)客戶(hù)提高一站式互聯(lián)網(wǎng)+設(shè)計(jì)服務(wù),主要包括成都網(wǎng)站建設(shè)、做網(wǎng)站手機(jī)APP定制開(kāi)發(fā)、微信小程序開(kāi)發(fā)、宣傳片制作、LOGO設(shè)計(jì)等,幫助客戶(hù)快速提升營(yíng)銷(xiāo)能力和企業(yè)形象,創(chuàng)新互聯(lián)各部門(mén)都有經(jīng)驗(yàn)豐富的經(jīng)驗(yàn),可以確保每一個(gè)作品的質(zhì)量和創(chuàng)作周期,同時(shí)每年都有很多新員工加入,為我們帶來(lái)大量新的創(chuàng)意。 1. 線(xiàn)程異步的概念

問(wèn)題1: 如何理解線(xiàn)程異步?

?異步的反義詞是同步。異步與同步的區(qū)別見(jiàn)此處: [[Linux/計(jì)算機(jī)網(wǎng)絡(luò)基礎(chǔ)知識(shí)點(diǎn)/高級(jí)IO#同步通信 vs 異步通信]]。實(shí)際上在多線(xiàn)程下,大部分時(shí)候都是存在過(guò)異步這一狀態(tài)的。主線(xiàn)程在創(chuàng)建了子線(xiàn)程后,也去干自己的任務(wù)了。

問(wèn)題2: 線(xiàn)程異步的應(yīng)用場(chǎng)景?

  1. 主線(xiàn)程想要得到某一子線(xiàn)程運(yùn)行的任務(wù)函數(shù)的運(yùn)行結(jié)果。這里的結(jié)果可以使用future對(duì)象進(jìn)行存儲(chǔ)。(future是個(gè)模板類(lèi), 能存儲(chǔ)任意類(lèi)型, 包括void)//子—>主
  2. 主線(xiàn)程想要通知子線(xiàn)程, 依靠future值和狀態(tài) 來(lái)達(dá)成某一目的(讓子線(xiàn)程結(jié)束/滿(mǎn)足條件/…), 此時(shí)主線(xiàn)程在外面設(shè)置future對(duì)象的共享狀態(tài)及future值。子線(xiàn)程那邊可以根據(jù)future對(duì)象的狀態(tài)和值進(jìn)行一些邏輯判斷然后到達(dá)想要的結(jié)果。//主—>子

?

2. future
//包含于頭文件
templatefuture;
templatefuture;     // specialization : T is a reference type (R&)
template<> future;   // specialization : T is void
//---------------------------------------------------
//構(gòu)造函數(shù)
future() noexcept;					//(1) default
future (const future&) = delete;	//(2) copy [deleted]
future (future&& x) noexcept;		//(3) move

//賦值
future& operator=(future&& other) noexcept;
future& operator=(const future& other) = delete;

?
?future對(duì)象是用于存儲(chǔ)某一類(lèi)型的值的,只不過(guò)這個(gè)值往往是在未來(lái)才能獲取到。 它被用來(lái)作為線(xiàn)程異步的中間存儲(chǔ)值。future的值由以下三個(gè)異步任務(wù)的提供者(Provider)提供:

  1. std::promise
  2. std::package_task
  3. std::async

?我們根據(jù)future的構(gòu)造函數(shù)可以發(fā)現(xiàn),future不支持拷貝構(gòu)造。future的operator=()會(huì)去調(diào)用移動(dòng)構(gòu)造。

?

2.1 共享狀態(tài)

?future在線(xiàn)程異步當(dāng)中扮演的是一個(gè)被動(dòng)角色。它需要與promisepackage_task、async配合來(lái)實(shí)現(xiàn)線(xiàn)程異步。由于它必須要進(jìn)行共享關(guān)聯(lián),因此future對(duì)象時(shí)存在共享狀態(tài)是否有效的問(wèn)題的。只有共享狀態(tài)有效,才能獲取future的值。

?future對(duì)象是有"共享狀態(tài)"這一概念的。共享狀態(tài)必須依靠上面提到的三者對(duì)應(yīng)的方法:promise::get_future()package_task::get_future()、async()獲取。否則單純的創(chuàng)建一個(gè)future對(duì)象, 它的共享狀態(tài)是無(wú)效的!

共享狀態(tài)解釋
future_status::deferred子線(xiàn)程中的任務(wù)函仍未啟動(dòng)
future_status::timeout子線(xiàn)程中的任務(wù)正在執(zhí)行中,指定等待時(shí)長(zhǎng)已用完
future_status::ready子線(xiàn)程中的任務(wù)已經(jīng)執(zhí)行完畢,結(jié)果已就緒

?實(shí)際上,為了方便我們理解,還應(yīng)該加一個(gè)狀態(tài): 無(wú)效狀態(tài)(invalid)。這個(gè)狀態(tài)存在于:
①future對(duì)象沒(méi)有接收任何提供者的共享關(guān)聯(lián);
②future對(duì)象ready完畢后,被調(diào)用者通過(guò)get()獲取過(guò)了。

?

2.2 常用成員函數(shù)
成員函數(shù)功能
valid()判斷共享狀態(tài)是否有效
wait()等待共享狀態(tài)ready
wait_for()等待一段時(shí)間
wait_until()等待到某個(gè)時(shí)間點(diǎn)
get()獲取future的值

注意:

  • 在調(diào)用get()時(shí),如果future的共享狀態(tài)不是ready, 則調(diào)用者會(huì)被阻塞。
  • get()只能被調(diào)用一次,第二次會(huì)拋出異常。(因?yàn)榈谝淮瓮瓿珊?,future的狀態(tài)就是無(wú)效的了)
  • 調(diào)用wait()方法會(huì)阻塞式等待共享狀態(tài)為ready。
  • wait_for()wait_until()無(wú)法保證等待結(jié)束后的future對(duì)象的狀態(tài)一定是ready! (所以它們不太常用, 因?yàn)檎{(diào)用完畢后還需要使用valid()判斷共享狀態(tài))
  • wait_for()wait_until()的返回值是std::future_status。因此我們可以通過(guò)接收它們的返回值來(lái)循環(huán)判斷future對(duì)象是否ready。

?

3. promise
//包含于頭文件
templatepromise;
templatepromise;  // specialization : T is a reference type (R&)
template<> promise;// specialization : T is void

//構(gòu)造函數(shù)
promise();								//(1)
promise(promise&& other) noexcept;		//(2) 移動(dòng)構(gòu)造
promise(const promise& other) = delete;	//(3) 禁止拷貝構(gòu)造

//賦值
promise& operator= (promise&& rhs) noexcept; //允許移動(dòng)賦值
promise& operator= (const promise&) = delete;//禁止拷貝賦值

?promise是一個(gè)協(xié)助線(xiàn)程賦值的類(lèi),在promise類(lèi)的內(nèi)部管理著一個(gè)future對(duì)象。因此它能夠提供一些將數(shù)據(jù)和future對(duì)象綁定起來(lái)的接口。

?

3.1 常用成員函數(shù)
成員函數(shù)功能
get_future()獲取future對(duì)象
set_value()設(shè)置future對(duì)象的值(立刻)
set_value_at_thread_exit()在線(xiàn)程結(jié)束時(shí),才會(huì)設(shè)置future對(duì)象的值,

?
? get_future()

?get_future()會(huì)返回一個(gè)future對(duì)象, 此時(shí)如果去接收它的返回值則會(huì)觸發(fā)移動(dòng)賦值, 將資源轉(zhuǎn)移。

? set_value()

?設(shè)置future對(duì)象的值,并立即設(shè)置future對(duì)象的共享狀態(tài)為ready。

? set_value_at_thread_exit()

?設(shè)置future對(duì)象的值,但是不會(huì)立刻讓future對(duì)象的共享狀態(tài)為ready。在子線(xiàn)程退出時(shí),子線(xiàn)程資源被銷(xiāo)毀,再令共享狀態(tài)為ready

?

3.2 promise的基本使用

①: 子線(xiàn)程set_value—>給主線(xiàn)程

  1. 在主線(xiàn)程中創(chuàng)建promise對(duì)象
  2. 將這個(gè)promise對(duì)象通過(guò)引用傳遞的方式傳給子線(xiàn)程的任務(wù)函數(shù)(ref)
  3. 子線(xiàn)程在合適的時(shí)候調(diào)用set_value()方法, 設(shè)置future對(duì)象的值以及狀態(tài)(ready)
  4. 主線(xiàn)程通過(guò)調(diào)用promise對(duì)象中的get_future()方法獲取到future對(duì)象 (這里是移動(dòng)構(gòu)造了)
  5. 主線(xiàn)程調(diào)用future對(duì)象中的get()方法獲取到子線(xiàn)程set_value()所設(shè)置的值。
    ?
void func(promise& pr)
{cout<< "Child Thread Working~~~"<< endl;
    cout<< "Child Thread: Waiting 3 seconds!"<< endl;
    this_thread::sleep_for(chrono::seconds(3));
    
    pr.set_value(3);
    this_thread::sleep_for(chrono::seconds(1));
    cout<< "Child Exit"<< endl;
}

int main()
{promisepr;
    thread t(func, ref(pr));
    auto f = pr.get_future();
    this_thread::sleep_for(chrono::seconds(1));
    cout<< "Get Future: "<< f.get()<< endl;
    t.join();
    return 0;
}

注意:

?根據(jù)現(xiàn)象, 我們可以發(fā)現(xiàn)主線(xiàn)程在調(diào)用f.get()時(shí)阻塞了一會(huì)。此時(shí)說(shuō)明子線(xiàn)程還沒(méi)有執(zhí)行到set_value(), 此時(shí)的future對(duì)象中的共享狀態(tài)不是ready, 因此主線(xiàn)程會(huì)被阻塞。


②: 主線(xiàn)程set_value–>給子線(xiàn)程

  1. 在主線(xiàn)程中創(chuàng)建promise對(duì)象
  2. 將這個(gè)promise對(duì)象通過(guò)引用傳遞的方式傳給子線(xiàn)程的任務(wù)函數(shù)(ref)
  3. 主線(xiàn)程在合適的時(shí)候調(diào)用set_value()方法, 設(shè)置future對(duì)象的值以及狀態(tài)(ready)
  4. 在編碼子線(xiàn)程時(shí),設(shè)置依future對(duì)象的值的判斷條件,當(dāng)future的共享狀態(tài)或者值滿(mǎn)足條件時(shí),執(zhí)行某一任務(wù)(或終止)
void func2(promise& pr)
{int i = 0;
    auto val = pr.get_future().get();
    if(val == 1){cout<< "Get Value: "<< val<< endl;
        //do something
    }
    else{cout<< "Get Value: "<< val<< endl;
        //do something
    }
}

int main()
{promisepr;
    thread t(func2, ref(pr));
    cout<< "Main Thread: Waiting 3 seconds!"<< endl;
    this_thread::sleep_for(chrono::seconds(3));
    pr.set_value(1);
    t.join();
}

輸出:

Main Thread: Waiting 3 seconds!
Get Value: 1

?

?

4. package_task
//包含于頭文件
templatepackaged_task;     // undefined
templateclass packaged_task;

//構(gòu)造函數(shù)
packaged_task() noexcept;						//default (1)
templateexplicit packaged_task (Fn&& fn);				//initialization (2)
packaged_task (const packaged_task&) = delete;	//copy [deleted] (3)
packaged_task (packaged_task&& x) noexcept;		//move (4)

//賦值
packaged_task& operator=(packaged_task&& rhs) noexcept; //move (1)
packaged_task& operator=(const packaged_task&) = delete;//copy [deleted] (2)

?package_task包裝了一個(gè)函數(shù)對(duì)象(類(lèi)似于function), 我們可以把它當(dāng)做函數(shù)對(duì)象來(lái)使用。package_task可以將內(nèi)部包裝的函數(shù)和future綁定到一起,以便于進(jìn)行后續(xù)的異步調(diào)用。因此我們可以將其理解為它自帶了一個(gè)函數(shù),并且該函數(shù)和future對(duì)象綁定到了一起,我們不需要額外定義函數(shù)方法了,直接實(shí)現(xiàn)package_task中的函數(shù)對(duì)象即可。

?但package_task相比于promise有個(gè)缺點(diǎn),它里面包裝了函數(shù),而該函數(shù)的返回值就是future對(duì)象的值。它無(wú)法像使用promise那樣靈活。

?

4.1 常用成員函數(shù)

?package_task中最常用的就是get_future()方法了。它能夠獲取到package_task中的future對(duì)象。

?

4.2 package_task的基本使用

?將package_task作為線(xiàn)程的啟動(dòng)函數(shù)傳過(guò)去,傳參方式必須是引用傳遞 ref()。

int main()
{packaged_taskpt_Add([](int x, int y)
    {cout<< "Running~~~~~~~~~~"<< endl;
        this_thread::sleep_for(chrono::seconds(3));
        return x + y;
    });

    futurefi = pt_Add.get_future();

    cout<< "Start Thread!"<< endl;
    thread t(ref(pt_Add), 10, 20);

    cout<< "before get"<< endl;
    int val = fi.get();
    cout<< "val: "<< val<< endl;
    t.join();
    return 0;
}

輸出:

Start Thread!
before get
Running~~~~~~~~~~
val: 30

?

?

5. async
//構(gòu)造函數(shù)
// (1)
templatefuture::type>async (Fn&& fn, Args&&... args);

// (2)
templatefuture::type>async (launch policy, Fn&& fn, Args&&... args);	//policy是啟動(dòng)策略

?async是一個(gè)函數(shù),它相比于前面的promise和package_task要高級(jí)一些。async可以直接啟動(dòng)一個(gè)子線(xiàn)程,然后讓這個(gè)子線(xiàn)程執(zhí)行對(duì)應(yīng)的任務(wù)函數(shù),任務(wù)函數(shù)的返回值就會(huì)被存儲(chǔ)到future對(duì)象當(dāng)中,future對(duì)象也就是async函數(shù)的返回值。主線(xiàn)程只需要接收asnyc的返回值,然后調(diào)用get()方法即可獲取到future對(duì)象中保存的值。

注: 更高級(jí)并不代表更好用,只是它的集成度更高一些,省去了我們要自己創(chuàng)建線(xiàn)程的步驟。async仍然有package_task的缺點(diǎn),它無(wú)法像promise那樣自由控制future在何時(shí)賦值。

?

? launch policy啟動(dòng)策略

策略解釋
std::launch::async調(diào)用async函數(shù)時(shí)會(huì)創(chuàng)建新的線(xiàn)程,讓該線(xiàn)程執(zhí)行任務(wù)函數(shù)
std::launch::deferred調(diào)用async函數(shù)時(shí)不會(huì)創(chuàng)建新的線(xiàn)程,也不會(huì)去執(zhí)行該任務(wù)函數(shù)。只有調(diào)用了async返回的future的get()方法或者wait()方法時(shí)才會(huì)去執(zhí)行任務(wù)。(執(zhí)行該任務(wù)的是主線(xiàn)程)

?

5.1 async的基本使用

? 使用默認(rèn)的啟動(dòng)策略 — 調(diào)用async創(chuàng)建子線(xiàn)程, 并讓該線(xiàn)程去執(zhí)行任務(wù)

int main()
{futuref = async([](int x, int y)
   {   cout<< "Child Thread: Waiting 3 seconds!"<< endl;
       this_thread::sleep_for(chrono::seconds(3));
       return x + y;
   }, 10, 20);

   this_thread::sleep_for(chrono::seconds(1));
   cout<< "Get Value: "<< f.get()<< endl;
   return 0;
}

輸出:

Child Thread: Waiting 3 seconds!
Get Value: 30


? 使用deferred啟動(dòng)策略 — 調(diào)用async不創(chuàng)建子線(xiàn)程

int main()
{futuref = async(launch::deferred, [](int x, int y)
    {cout<< "Child Thread "<< this_thread::get_id()<< ": Waiting 3 seconds!"<< endl;
        this_thread::sleep_for(chrono::seconds(3));
        return x + y;
    }, 10, 20);

    cout<< "Main Thread "<< this_thread::get_id()<<": Working!!!"<< endl;
    auto val = f.get();
    cout<< "Get Value: "<< val<< endl;
	return 0;
}

輸出:

Main Thread 1: Working!!!
Child Thread 1: Waiting 3 seconds!
Get Value: 30

?我們可以發(fā)現(xiàn)使用deferred策略時(shí),是不會(huì)創(chuàng)建新的線(xiàn)程的。也就是說(shuō)async的任務(wù)函數(shù)依然是由主線(xiàn)程自己去執(zhí)行的,只不過(guò)執(zhí)行的時(shí)機(jī)可以控制 (在調(diào)用get()方法時(shí)會(huì)去執(zhí)行),這個(gè)機(jī)制類(lèi)似于回調(diào)函數(shù),你主動(dòng)去調(diào)用get()才會(huì)去回調(diào)執(zhí)行async的任務(wù)。

?

?

6. promise、package_task、async的對(duì)比與總結(jié)
  1. promise類(lèi)的使用相對(duì)靈活,但是需要自己創(chuàng)建線(xiàn)程,并且需要自己寫(xiě)一個(gè)函數(shù)對(duì)象。
  2. package_task類(lèi)受限于只能使用函數(shù)返回值作為future對(duì)象的值。使用它也需要自己創(chuàng)建線(xiàn)程,但不需要額外寫(xiě)函數(shù)對(duì)象,直接將package_task當(dāng)做函數(shù)對(duì)象去使用即可。
  3. async類(lèi)集合度較高,它也受限于只能使用函數(shù)返回值作為future對(duì)象的值。但是async定義時(shí)可以自動(dòng)創(chuàng)建線(xiàn)程,并讓線(xiàn)程執(zhí)行async中的任務(wù)函數(shù)。async的使用最簡(jiǎn)單,但是自由度較低。

?

細(xì)節(jié)總結(jié):

  1. 調(diào)用get_future()方法, 并不會(huì)讓線(xiàn)程被阻塞。只要調(diào)用future對(duì)象的get()方法,才可能被阻塞。(future共享狀態(tài)沒(méi)有ready就會(huì)被阻塞, 前提是future共享狀態(tài)有效)
  2. 創(chuàng)建線(xiàn)程時(shí),給線(xiàn)程傳參要注意使用ref()的時(shí)機(jī)。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

分享標(biāo)題:C++11線(xiàn)程異步-創(chuàng)新互聯(lián)
文章來(lái)源:http://www.rwnh.cn/article24/djgoje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、定制開(kāi)發(fā)、軟件開(kāi)發(fā)網(wǎng)站改版、企業(yè)建站、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)
广丰县| 讷河市| 玛纳斯县| 尖扎县| 平乡县| 凤凰县| 沐川县| 沧源| 成都市| 施甸县| 仁怀市| 县级市| 井陉县| 浦东新区| 辽宁省| 樟树市| 万载县| 昌邑市| 邯郸县| 平谷区| 文安县| 桑植县| 即墨市| 贵定县| 商都县| 临高县| 东乡族自治县| 鄂托克前旗| 承德市| 沧州市| 孝昌县| 津市市| 胶州市| 永登县| 和平县| 内丘县| 兴义市| 紫金县| 屏东市| 阿克陶县| 桐城市|