日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【Boost】boost库中thread多线程详解1——thread入门与简介

發(fā)布時(shí)間:2024/4/11 编程问答 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Boost】boost库中thread多线程详解1——thread入门与简介 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 概述

線程就是,在同一程序同一時(shí)間內(nèi)允許執(zhí)行不同函數(shù)的離散處理隊(duì)列。 這使得一個(gè)長(zhǎng)時(shí)間去進(jìn)行某種特殊運(yùn)算的函數(shù)在執(zhí)行時(shí)不阻礙其他的函數(shù)變得十分重要。 線程實(shí)際上允許同時(shí)執(zhí)行兩種函數(shù),而這兩個(gè)函數(shù)不必相互等待。 一旦一個(gè)應(yīng)用程序啟動(dòng),它僅包含一個(gè)默認(rèn)線程。 此線程執(zhí)行main() 函數(shù)。 在main()中被調(diào)用的函數(shù)則按這個(gè)線程的上下文順序地執(zhí)行。 這樣的程序稱為單線程程序。 反之,那些創(chuàng)建新的線程的程序就是多線程程序。 他們不僅可以在同一時(shí)間執(zhí)行多個(gè)函數(shù),而且這在如今多核盛行的時(shí)代顯得尤為重要。 既然多核允許同時(shí)執(zhí)行多個(gè)函數(shù),這就使得對(duì)開發(fā)人員相應(yīng)地使用這種處理能力提出了要求。 然而線程一直被用來(lái)當(dāng)并發(fā)地執(zhí)行多個(gè)函數(shù),開發(fā)人員現(xiàn)在不得不仔細(xì)地構(gòu)建應(yīng)用來(lái)支持這種并發(fā)。 多線程編程知識(shí)也因此在多核系統(tǒng)時(shí)代變得越來(lái)越重要。

2. 線程管理

2.1 情景1(test_thread_wait1)

在這個(gè)庫(kù)最重要的一個(gè)類就是boost::thread,它是在boost/thread.hpp里定義的,用來(lái)創(chuàng)建一個(gè)新線程。下面的示例來(lái)說(shuō)明如何運(yùn)用它。 新建線程里執(zhí)行的那個(gè)函數(shù)的名稱被傳遞到boost::thread的構(gòu)造函數(shù)。 一旦上述示例中的變量t 被創(chuàng)建,該 thread() 函數(shù)就在其所在線程中被立即執(zhí)行。 同時(shí)在test_thread_wait1()里也并發(fā)地執(zhí)行該 threadfun1() 。 為了防止程序終止,就需要對(duì)新建線程調(diào)用join() 方法。join() 方法是一個(gè)阻塞調(diào)用:它可以暫停當(dāng)前線程,直到調(diào)用 join() 的線程運(yùn)行結(jié)束。這就使得test_thread_wait1()函數(shù)一直會(huì)等待到 threadfun1()運(yùn)行結(jié)束。 正如在上面的例子中看到,一個(gè)特定的線程可以通過諸如t的變量訪問,通過這個(gè)變量等待著它的使用 join() 方法終止。 但是,即使 t 越界或者析構(gòu)了,該線程也將繼續(xù)執(zhí)行。 一個(gè)線程總是在一開始就綁定到一個(gè)類型為 boost::thread 的變量,但是一旦創(chuàng)建,就不在取決于它。 甚至還存在著一個(gè)叫detach()的方法,允許類型為boost::thread 的變量從它對(duì)應(yīng)的線程里分離。 當(dāng)然了,像join()的方法之后也就不能被調(diào)用,因?yàn)檫@個(gè)變量不再是一個(gè)有效的線程。 任何一個(gè)函數(shù)內(nèi)可以做的事情也可以在一個(gè)線程內(nèi)完成。 歸根結(jié)底,一個(gè)線程只不過是一個(gè)函數(shù),除了它是同時(shí)執(zhí)行的。 在上述例子中,使用一個(gè)循環(huán)把5個(gè)數(shù)字寫入標(biāo)準(zhǔn)輸出流。 為了減緩輸出,每一個(gè)循環(huán)中調(diào)用wait() 函數(shù)讓執(zhí)行延遲了一秒。 wait() 可以調(diào)用一個(gè)名為sleep() 的函數(shù),這個(gè)函數(shù)也來(lái)自于 Boost.Thread,位于 boost::this_thread 名空間內(nèi)。 sleep() 要么在預(yù)計(jì)的一段時(shí)間或一個(gè)特定的時(shí)間點(diǎn)后時(shí)才讓線程繼續(xù)執(zhí)行。 通過傳遞一個(gè)類型為boost::posix_time::seconds 的對(duì)象,在這個(gè)例子里我們指定了一段時(shí)間。 boost::posix_time::seconds 來(lái)自于Boost.DateTime庫(kù),它被 Boost.Thread 用來(lái)管理和處理時(shí)間的數(shù)據(jù)。 雖然前面的例子說(shuō)明了如何等待一個(gè)不同的線程,但下面的例子演示了如何通過所謂的中斷點(diǎn)讓一個(gè)線程中斷。

2.2?情景2(test_thread_wait2())

在一個(gè)線程對(duì)象上調(diào)用 interrupt() 會(huì)中斷相應(yīng)的線程。在這方面,中斷意味著一個(gè)類型為boost::thread_interrupted的異常,它會(huì)在這個(gè)線程中拋出。然后這只有在線程達(dá)到中斷點(diǎn)時(shí)才會(huì)發(fā)生。如果給定的線程不包含任何中斷點(diǎn),簡(jiǎn)單調(diào)用interrupt() 就不會(huì)起作用。每當(dāng)一個(gè)線程中斷點(diǎn),它就會(huì)檢查interrupt() 是否被調(diào)用過。只有被調(diào)用過了, boost::thread_interrupted 異常才會(huì)相應(yīng)地拋出。Boost.Thread定義了一系列的中斷點(diǎn),例如sleep()函數(shù)。由于sleep()在這個(gè)例子里被調(diào)用了五次,該線程就檢查了五次它是否應(yīng)該被中斷。然而sleep()之間的調(diào)用,卻不能使線程中斷。一旦該程序被執(zhí)行,它只會(huì)打印三個(gè)數(shù)字到標(biāo)準(zhǔn)輸出流。這是由于在test_thread_wait2()里3秒后調(diào)用 interrupt()方法。因此,相應(yīng)的線程被中斷,并拋出一個(gè)boost::thread_interrupted 異常。 這個(gè)異常在線程內(nèi)也被正確地捕獲,catch處理雖然是空的。由于thread() 函數(shù)在處理程序后返回,線程也被終止。這反過來(lái)也將終止整個(gè)程序,因?yàn)閠est_thread_wait2()等待該線程使用join()終止該線程。Boost.Thread定義包括上述 sleep()函數(shù)十個(gè)中斷。有了這些中斷點(diǎn),線程可以很容易及時(shí)中斷。然而,他們并不總是最佳的選擇,因?yàn)橹袛帱c(diǎn)必須事前讀入以檢查boost::thread_interrupted異常。

看下面一個(gè)小例子:

#include "stdafx.h" #include <iostream> #include <boost/thread.hpp> using namespace std;#define PRINT_DEBUG(x) cout<< x <<endl;void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } void threadfun1() { for (int i = 0; i < 5; ++i) { wait(1); PRINT_DEBUG(i); } } void threadfun2() { try { for (int i = 0; i < 5; ++i) { wait(1); PRINT_DEBUG(i); } } catch (boost::thread_interrupted&) { PRINT_DEBUG("thread_interrupted"); } } void test_thread_wait1() { boost::thread t(&threadfun1);//join()方法是一個(gè)阻塞調(diào)用:它可以暫停當(dāng)前線程,直到調(diào)用join()的線程運(yùn)行結(jié)束。 t.join(); } void test_thread_wait2() { boost::thread t(&threadfun2); wait(3); t.interrupt(); t.join(); } void test_thread_wait3() { boost::thread t(&threadfun1); // timed_join()方法同樣也是一個(gè)阻塞調(diào)用:它可以暫停當(dāng)前線程, // 直到調(diào)用join()的線程運(yùn)行結(jié)束或者超時(shí) t.timed_join(boost::posix_time::seconds(3)); } void test_thread_wait4() { boost::thread t(&threadfun2); wait(3); //當(dāng)thread 與線程執(zhí)行體分離時(shí),線程執(zhí)行體將不受影響地繼續(xù)執(zhí)行, //直到運(yùn)行結(jié)束,或者隨主線程一起結(jié)束。 t.detach(); // 此時(shí)join無(wú)作用 t.join(); // t不再標(biāo)識(shí)任何線程 {Not-any-thread} assert(t.get_id() == boost::thread::id()); } int _tmain(int argc, _TCHAR* argv[]) {test_thread_wait4();return 0; }


一、創(chuàng)建一個(gè)線程

創(chuàng)建線程

??? 當(dāng)一個(gè)thread執(zhí)行完成時(shí),這個(gè)子線程就會(huì)消失。注意這個(gè)線程對(duì)象不會(huì)消失,它仍然是一個(gè)還處在它的生存期的C++對(duì)象。同理,當(dāng)對(duì)一個(gè)堆上的線程對(duì)象的指針調(diào)用delete時(shí)候,線程對(duì)象被銷毀,操作系統(tǒng)的線程并不能保證就消失。

放棄時(shí)間片

??? boost::thread::yield(); (暫時(shí)沒有看出來(lái)它的實(shí)際作用)

??? 當(dāng)前線程放棄余下的時(shí)間片。

等待一個(gè)線程

??? myThread.join();(類似windows API?WaitForSingleObject

??? 調(diào)用這個(gè)方法的線程進(jìn)入wait狀態(tài),直到myThread代表的線程完成為止。如果它不結(jié)束的話,join方法就不會(huì)返回。join是一個(gè)等待子線程結(jié)束的最好的方法。如果主程序不調(diào)用join方法而直接結(jié)束,它的子線程有可能沒有執(zhí)行完成,但是所有的子線程也隨之退出。不調(diào)用join方法,主線程就不會(huì)等待它的子線程。

#include <iostream> #include <boost/thread/thread.hpp> #include <boost/thread/xtime.hpp>struct MyThreadFunc {void operator( )( ) {// Do something long-running...} } threadFun;int main( ) {boost::thread myThread(threadFun);// Create a thread that starts// running threadFunboost::thread::yield( ); // Give up the main thread's timeslice// so the child thread can get some work// done.// Go do some other work...myThread.join( ); // The current (i.e., main) thread will wait// for myThread to finish before it returns}

l?boost::thread?

????boost::thread?是Boost庫(kù)對(duì)thread的封裝,隱藏了特定于操作系統(tǒng)的實(shí)現(xiàn),提供給用戶統(tǒng)一的接口,實(shí)現(xiàn)了跨平臺(tái),同時(shí)使用戶從繁雜的thread的特定于操作系統(tǒng)的API中解脫出來(lái),取而代之的是更易理解、更優(yōu)美的對(duì)象。每個(gè)thread對(duì)象代表一個(gè)線程。


一.?使用boost::thread創(chuàng)建線程

由于每一個(gè)boost::thread對(duì)應(yīng)一個(gè)線程,所以創(chuàng)建線程就是創(chuàng)建一個(gè)boost::thread對(duì)象。

template<typename?Callable>

thread(Callable?func);

這里需要一個(gè)函數(shù)對(duì)象(函數(shù)指針、仿函數(shù))

A?仿函數(shù)(測(cè)試失敗,不知道怎們回事回調(diào)不成功)

struct callable {void operator()(void){std::cout << "In callable ..." << std::endl;} }; boost::thread thread_call(struct callable);callable c; boost::thread thread_call(c); ?//這樣就可以了

B.全局函數(shù).?

void func() {std::cout << "In fun..." << std::endl; } boost::thread thread_func(func);

C.?類成員函數(shù)

借助boost::bind?輕松實(shí)現(xiàn)

class thread_test {public:void invoke(){std::cout << "In thread_test::invoke..." << std::endl;} }; thread_test athread_test; boost::thread thread_member_call(boost::bind(&thread_test::invoke,&athread_test));

D.?含參函數(shù)對(duì)象

void func_arg(int num) {std::cout << "In func_arg ..." << " num=" << num << std::endl; } boost::thread thread_arg_bind(boost::bind(&func_arg,1012)); boost::thread thread_arg(func_arg,2012);


Boost::thread?中重載的構(gòu)造

template?<class?F,class?A1,class?A2,...>

thread(F?f,A1?a1,A2?a2,...);

其實(shí)他內(nèi)部也是通過boost::bind創(chuàng)建函數(shù)對(duì)象。

thread(boost::bind(f,a1,a2,...))


六、給線程函數(shù)傳遞一個(gè)參數(shù)

#include <iostream> #include <string> #include <functional> #include <boost/thread/thread.hpp>// A typedef to make the declarations below easier to read typedef void (*WorkerFunPtr)(const std::string&);template<typename FunT, // The type of the function being calledtypename ParamT>// The type of its parameter struct Adapter {Adapter(FunT f, ParamT& p) : // Construct this adapter and set thef_(f), p_(&p) {} // members to the function and its argvoid operator( )( ) { // This just calls the function with its argf_(*p_); } private:FunT f_;ParamT* p_; // Use the parameter's address to avoid extra copying };void worker(const std::string& s) {std::cout << s << '\n'; }int main( ) {std::string s1 = "This is the first thread!";std::string s2 = "This is the second thread!";boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));boost::thread thr2(Adapter<WorkerFunPtr, std::string>(worker, s2));thr1.join( );thr2.join( ); }

使用這個(gè)函數(shù)適配器類模板,你就可以給線程函數(shù)傳遞參數(shù)了。如果你需要傳遞多個(gè)參數(shù),僅需要在這個(gè)適配器中增加另一個(gè)類型和成員變量。


BOOST庫(kù)的未來(lái):

Boost線程庫(kù)正在計(jì)劃加入一些新特性。其中包括boost::read_write_mutex,它可以讓多個(gè)線程同時(shí)從共享區(qū)中讀取數(shù)據(jù),但是一次只可能有一個(gè)線程向共享區(qū)寫入數(shù)據(jù);boost::thread_barrier,它使得一組線程處于等待狀態(tài),知道所有得線程都都進(jìn)入了屏障區(qū);boost::thread_pool,他允許執(zhí)行一些小的routine而不必每一都要?jiǎng)?chuàng)建或是銷毀一個(gè)線程。Boost線程庫(kù)已經(jīng)作為標(biāo)準(zhǔn)中的類庫(kù)技術(shù)報(bào)告中的附件提交給C++標(biāo)準(zhǔn)委員會(huì),它的出現(xiàn)也為下一版C++標(biāo)準(zhǔn)吹響了第一聲號(hào)角。委員會(huì)成員對(duì)Boost線程庫(kù)的初稿給予了很高的評(píng)價(jià),當(dāng)然他們還會(huì)考慮其他的多線程庫(kù)。他們對(duì)在C++標(biāo)準(zhǔn)中加入對(duì)多線程的支持非常感興趣。從這一點(diǎn)上也可以看出,多線程在C++中的前途一片光明。


總結(jié)

以上是生活随笔為你收集整理的【Boost】boost库中thread多线程详解1——thread入门与简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。