作者:
dozb
標(biāo)準(zhǔn)C++線(xiàn)程即將到來(lái)。CUJ預(yù)言它將衍生自Boost線(xiàn)程庫(kù),現(xiàn)在就由Bill帶領(lǐng)我們探索一下Boost線(xiàn)程庫(kù)。
就在幾年前,用多線(xiàn)程執(zhí)行程序還是一件非比尋常的事。然而今天互聯(lián)網(wǎng)應(yīng)用服務(wù)程序普遍使用多線(xiàn)程來(lái)提高與多客戶(hù)鏈接時(shí)的效率;為了達(dá)到最大的吞吐量,事務(wù)服務(wù)器在單獨(dú)的線(xiàn)程上運(yùn)行服務(wù)程序;GUI應(yīng)用程序?qū)⒛切┵M(fèi)時(shí),復(fù)雜的處理以線(xiàn)程的形式單獨(dú)運(yùn)行,以此來(lái)保證用戶(hù)界面能夠及時(shí)響應(yīng)用戶(hù)的操作。這樣使用多線(xiàn)程的例子還有很多。
但是C++標(biāo)準(zhǔn)并沒(méi)有涉及到多線(xiàn)程,這讓程序員們開(kāi)始懷疑是否可能寫(xiě)出多線(xiàn)程的C++程序。盡管不可能寫(xiě)出符合標(biāo)準(zhǔn)的多線(xiàn)程程序,但是程序員們還是會(huì)使用支持多線(xiàn)程的操作系統(tǒng)提供的多線(xiàn)程庫(kù)來(lái)寫(xiě)出多線(xiàn)程C++程序。但是這樣做至少有兩個(gè)問(wèn)題:這些庫(kù)大部分都是用C語(yǔ)言完成的,如果在C++程序中要使用這些庫(kù)就必須十分小心;還有,每一個(gè)操作系統(tǒng)都有自己的一套支持多線(xiàn)程的類(lèi)庫(kù)。因此,這樣寫(xiě)出來(lái)得代碼是沒(méi)有標(biāo)準(zhǔn)可循的,也不是到處都適用的(non-portable)。Boost線(xiàn)程庫(kù)就是為了解決所有這些問(wèn)題而設(shè)計(jì)的。
Boost是由C++標(biāo)準(zhǔn)委員會(huì)類(lèi)庫(kù)工作組成員發(fā)起,致力于為C++開(kāi)發(fā)新的類(lèi)庫(kù)的組織。現(xiàn)在它已經(jīng)有近2000名成員。許多庫(kù)都可以在Boost源碼的發(fā)布版本中找到。為了使這些類(lèi)庫(kù)是線(xiàn)程安全的(thread-safe),Boost線(xiàn)程庫(kù)被創(chuàng)建了。
許多C++專(zhuān)家都投身于Boost線(xiàn)程庫(kù)的開(kāi)發(fā)中。所有接口的設(shè)計(jì)都是從0開(kāi)始的,并不是C線(xiàn)程API的簡(jiǎn)單封裝。許多C++特性(比如構(gòu)造函數(shù)和析構(gòu)函數(shù),函數(shù)對(duì)象(function object)和模板)都被使用在其中以使接口更加靈活。現(xiàn)在的版本可以在POSIX,Win32和Macintosh Carbon平臺(tái)下工作。
就像std::fstream類(lèi)就代表一個(gè)文件一樣,boost::thread類(lèi)就代表一個(gè)可執(zhí)行的線(xiàn)程。缺省構(gòu)造函數(shù)創(chuàng)建一個(gè)代表當(dāng)前執(zhí)行線(xiàn)程的實(shí)例。一個(gè)重載的構(gòu)造函數(shù)以一個(gè)不需任何參數(shù)的函數(shù)對(duì)象作為參數(shù),并且沒(méi)有返回值。這個(gè)構(gòu)造函數(shù)創(chuàng)建一個(gè)新的可執(zhí)行線(xiàn)程,它調(diào)用了那個(gè)函數(shù)對(duì)象。
起先,大家認(rèn)為傳統(tǒng)C創(chuàng)建線(xiàn)程的方法似乎比這樣的設(shè)計(jì)更有用,因?yàn)镃創(chuàng)建線(xiàn)程的時(shí)候會(huì)傳入一個(gè)void*指針,通過(guò)這種方法就可以傳入數(shù)據(jù)。然而,由于Boost線(xiàn)程庫(kù)是使用函數(shù)對(duì)象來(lái)代替函數(shù)指針,那么函數(shù)對(duì)象本身就可以攜帶線(xiàn)程所需的數(shù)據(jù)。這種方法更具靈活性,也是類(lèi)型安全(type-safe)的。當(dāng)和Boost.Bind這樣的功能庫(kù)一起使用時(shí),這樣的方法就可以讓你傳遞任意數(shù)量的數(shù)據(jù)給新建的線(xiàn)程。
目前,由Boost線(xiàn)程庫(kù)創(chuàng)建的線(xiàn)程對(duì)象功能還不是很強(qiáng)大。事實(shí)上它只能做兩項(xiàng)操作。線(xiàn)程對(duì)象可以方便使用==和!=進(jìn)行比較來(lái)確定它們是否是代表同一個(gè)線(xiàn)程;你還可以調(diào)用boost::thread::join來(lái)等待線(xiàn)程執(zhí)行完畢。其他一些線(xiàn)程庫(kù)可以讓你對(duì)線(xiàn)程做一些其他操作(比如設(shè)置優(yōu)先級(jí),甚至是取消線(xiàn)程)。然而,由于要在普遍適用(portable)的接口中加入這些操作不是簡(jiǎn)單的事,目前仍在討論如何將這些操組加入到Boost線(xiàn)程庫(kù)中。
Listing1展示了boost::thread類(lèi)的一個(gè)最簡(jiǎn)單的用法。 新建的線(xiàn)程只是簡(jiǎn)單的在std::out上打印“hello,world”,main函數(shù)在它執(zhí)行完畢之后結(jié)束。
例1:
#include <boost/thread/thread.hpp>
#include <iostream>
void hello()
{
std::cout <<
"Hello world, I'm a thread!"
<< std::endl;
}
int main(int argc, char* argv[])
{
boost::thread thrd(&hello);
thrd.join();
return 0;
}
任何寫(xiě)過(guò)多線(xiàn)程程序的人都知道避免不同線(xiàn)程同時(shí)訪(fǎng)問(wèn)共享區(qū)域的重要性。如果一個(gè)線(xiàn)程要改變共享區(qū)域中某個(gè)數(shù)據(jù),而與此同時(shí)另一線(xiàn)程正在讀這個(gè)數(shù)據(jù),那么結(jié)果將是未定義的。為了避免這種情況的發(fā)生就要使用一些特殊的原始類(lèi)型和操作。其中最基本的就是互斥體(mutex,mutual exclusion的縮寫(xiě))。一個(gè)互斥體一次只允許一個(gè)線(xiàn)程訪(fǎng)問(wèn)共享區(qū)。當(dāng)一個(gè)線(xiàn)程想要訪(fǎng)問(wèn)共享區(qū)時(shí),首先要做的就是鎖住(lock)互斥體。如果其他的線(xiàn)程已經(jīng)鎖住了互斥體,那么就必須先等那個(gè)線(xiàn)程將互斥體解鎖,這樣就保證了同一時(shí)刻只有一個(gè)線(xiàn)程能訪(fǎng)問(wèn)共享區(qū)域。
互斥體的概念有不少變種。Boost線(xiàn)程庫(kù)支持兩大類(lèi)互斥體,包括簡(jiǎn)單互斥體(simple mutex)和遞歸互斥體(recursive mutex)。如果同一個(gè)線(xiàn)程對(duì)互斥體上了兩次鎖,就會(huì)發(fā)生死鎖(deadlock),也就是說(shuō)所有的等待解鎖的線(xiàn)程將一直等下去。有了遞歸互斥體,單個(gè)線(xiàn)程就可以對(duì)互斥體多次上鎖,當(dāng)然也必須解鎖同樣次數(shù)來(lái)保證其他線(xiàn)程可以對(duì)這個(gè)互斥體上鎖。
在這兩大類(lèi)互斥體中,對(duì)于線(xiàn)程如何上鎖還有多個(gè)變種。一個(gè)線(xiàn)程可以有三種方法來(lái)對(duì)一個(gè)互斥體加鎖:
- 一直等到?jīng)]有其他線(xiàn)程對(duì)互斥體加鎖。
- 如果有其他互斥體已經(jīng)對(duì)互斥體加鎖就立即返回。
- 一直等到?jīng)]有其他線(xiàn)程互斥體加鎖,直到超時(shí)。
似乎最佳的互斥體類(lèi)型是遞歸互斥體,它可以使用所有三種上鎖形式。然而每一個(gè)變種都是有代價(jià)的。所以Boost線(xiàn)程庫(kù)允許你根據(jù)不同的需要使用最有效率的互斥體類(lèi)型。Boost線(xiàn)程庫(kù)提供了6中互斥體類(lèi)型,下面是按照效率進(jìn)行排序:
boost::mutex,
boost::try_mutex,
boost::timed_mutex,
boost::recursive_mutex,
boost::recursive_try_mutex,
boost::recursive_timed_mutex
如果互斥體上鎖之后沒(méi)有解鎖就會(huì)發(fā)生死鎖。這是一個(gè)很普遍的錯(cuò)誤,Boost線(xiàn)程庫(kù)就是要將其變成不可能(至少時(shí)很困難)。直接對(duì)互斥體上鎖和解鎖對(duì)于Boost線(xiàn)程庫(kù)的用戶(hù)來(lái)說(shuō)是不可能的。mutex類(lèi)通過(guò)teypdef定義在RAII中實(shí)現(xiàn)的類(lèi)型來(lái)實(shí)現(xiàn)互斥體的上鎖和解鎖。這也就是大家知道的Scope Lock模式。為了構(gòu)造這些類(lèi)型,要傳入一個(gè)互斥體的引用。構(gòu)造函數(shù)對(duì)互斥體加鎖,析構(gòu)函數(shù)對(duì)互斥體解鎖。C++保證了析構(gòu)函數(shù)一定會(huì)被調(diào)用,所以即使是有異常拋出,互斥體也總是會(huì)被正確的解鎖。
這種方法保證正確的使用互斥體。然而,有一點(diǎn)必須注意:盡管Scope Lock模式可以保證互斥體被解鎖,但是它并沒(méi)有保證在異常拋出之后貢獻(xiàn)資源仍是可用的。所以就像執(zhí)行單線(xiàn)程程序一樣,必須保證異常不會(huì)導(dǎo)致程序狀態(tài)異常。另外,這個(gè)已經(jīng)上鎖的對(duì)象不能傳遞給另一個(gè)線(xiàn)程,因?yàn)樗鼈兙S護(hù)的狀態(tài)并沒(méi)有禁止這樣做。
List2給出了一個(gè)使用boost::mutex的最簡(jiǎn)單的例子。例子中共創(chuàng)建了兩個(gè)新的線(xiàn)程,每個(gè)線(xiàn)程都有10次循環(huán),在std::cout上打印出線(xiàn)程id和當(dāng)前循環(huán)的次數(shù),而main函數(shù)等待這兩個(gè)線(xiàn)程執(zhí)行完才結(jié)束。std::cout就是共享資源,所以每一個(gè)線(xiàn)程都使用一個(gè)全局互斥體來(lái)保證同時(shí)只有一個(gè)線(xiàn)程能向它寫(xiě)入。
許多讀者可能已經(jīng)注意到List2中傳遞數(shù)據(jù)給線(xiàn)程還必須的手工寫(xiě)一個(gè)函數(shù)。盡管這個(gè)例子很簡(jiǎn)單,如果每一次都要寫(xiě)這樣的代碼實(shí)在是讓人厭煩的事。別急,有一種簡(jiǎn)單的解決辦法。函數(shù)庫(kù)允許你通過(guò)將另一個(gè)函數(shù)綁定,并傳入調(diào)用時(shí)需要的數(shù)據(jù)來(lái)創(chuàng)建一個(gè)新的函數(shù)。 List3向你展示了如何使用Boost.Bind庫(kù)來(lái)簡(jiǎn)化List2中的代碼,這樣就不必手工寫(xiě)這些函數(shù)對(duì)象了。
例2:
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
boost::mutex io_mutex;
struct count
{
count(int id) : id(id) { }
void operator()()
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": "
<< i << std::endl;
}
}
int id;
};
int main(int argc, char* argv[])
{
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
return 0;
}
例3: // 這個(gè)例子和例2一樣,除了使用Boost.Bind來(lái)簡(jiǎn)化創(chuàng)建線(xiàn)程攜帶數(shù)據(jù),避免使用函數(shù)對(duì)象
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex io_mutex;
void count(int id)
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": " <<
i << std::endl;
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1(
boost::bind(&count, 1));
boost::thread thrd2(
boost::bind(&count, 2));
thrd1.join();
thrd2.join();
return 0;
}
有的時(shí)候僅僅依靠鎖住共享資源來(lái)使用它是不夠的。有時(shí)候共享資源只有某些狀態(tài)的時(shí)候才能夠使用。比方說(shuō),某個(gè)線(xiàn)程如果要從堆棧中讀取數(shù)據(jù),那么如果棧中沒(méi)有數(shù)據(jù)就必須等待數(shù)據(jù)被壓棧。這種情況下的同步使用互斥體是不夠的。另一種同步的方式--條件變量,就可以使用在這種情況下。
條件變量的使用總是和互斥體及共享資源聯(lián)系在一起的。線(xiàn)程首先鎖住互斥體,然后檢驗(yàn)共享資源的狀態(tài)是否處于可使用的狀態(tài)。如果不是,那么線(xiàn)程就要等待條件變量。要指向這樣的操作就必須在等待的時(shí)候?qū)⒒コ怏w解鎖,以便其他線(xiàn)程可以訪(fǎng)問(wèn)共享資源并改變其狀態(tài)。它還得保證從等到得線(xiàn)程返回時(shí)互斥體是被上鎖得。當(dāng)另一個(gè)線(xiàn)程改變了共享資源的狀態(tài)時(shí),它就要通知正在等待條件變量得線(xiàn)程,并將之返回等待的線(xiàn)程。
List4是一個(gè)使用了boost::condition的簡(jiǎn)單例子。有一個(gè)實(shí)現(xiàn)了有界緩存區(qū)的類(lèi)和一個(gè)固定大小的先進(jìn)先出的容器。由于使用了互斥體boost::mutex,這個(gè)緩存區(qū)是線(xiàn)程安全的。put和get使用條件變量來(lái)保證線(xiàn)程等待完成操作所必須的狀態(tài)。有兩個(gè)線(xiàn)程被創(chuàng)建,一個(gè)在buffer中放入100個(gè)整數(shù),另一個(gè)將它們從buffer中取出。這個(gè)有界的緩存一次只能存放10個(gè)整數(shù),所以這兩個(gè)線(xiàn)程必須周期性的等待另一個(gè)線(xiàn)程。為了驗(yàn)證這一點(diǎn),put和get在std::cout中輸出診斷語(yǔ)句。最后,當(dāng)兩個(gè)線(xiàn)程結(jié)束后,main函數(shù)也就執(zhí)行完畢了。
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <iostream>
const int BUF_SIZE = 10;
const int ITERS = 100;
boost::mutex io_mutex;
class buffer
{
public:
typedef boost::mutex::scoped_lock
scoped_lock;
buffer()
: p(0), c(0), full(0)
{
}
void put(int m)
{
scoped_lock lock(mutex);
if (full == BUF_SIZE)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout <<
"Buffer is full. Waiting..."
<< std::endl;
}
while (full == BUF_SIZE)
cond.wait(lock);
}
buf[p] = m;
p = (p+1) % BUF_SIZE;
++full;
cond.notify_one();
}
int get()
{
scoped_lock lk(mutex);
if (full == 0)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout <<
"Buffer is empty. Waiting..."
<< std::endl;
}
while (full == 0)
cond.wait(lk);
}
int i = buf[c];
c = (c+1) % BUF_SIZE;
--full;
cond.notify_one();
return i;
}
private:
boost::mutex mutex;
boost::condition cond;
unsigned int p, c, full;
int buf[BUF_SIZE];
};
buffer buf;
void writer()
{
for (int n = 0; n < ITERS; ++n)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << "sending: "
<< n << std::endl;
}
buf.put(n);
}
}
void reader()
{
for (int x = 0; x < ITERS; ++x)
{
int n = buf.get();
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << "received: "
<< n << std::endl;
}
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1(&reader);
boost::thread thrd2(&writer);
thrd1.join();
thrd2.join();
return 0;
}
大多數(shù)函數(shù)都不是可重入的。這也就是說(shuō)在某一個(gè)線(xiàn)程已經(jīng)調(diào)用了一個(gè)函數(shù)時(shí),如果你再調(diào)用同一個(gè)函數(shù),那么這樣是不安全的。一個(gè)不可重入的函數(shù)通過(guò)連續(xù)的調(diào)用來(lái)保存靜態(tài)變量或者是返回一個(gè)指向靜態(tài)數(shù)據(jù)的指針。 舉例來(lái)說(shuō),std::strtok就是不可重入的,因?yàn)樗褂渺o態(tài)變量來(lái)保存要被分割成符號(hào)的字符串。
有兩種方法可以讓不可重用的函數(shù)變成可重用的函數(shù)。第一種方法就是改變接口,用指針或引用代替原先使用靜態(tài)數(shù)據(jù)的地方。比方說(shuō),POSIX定義了strok_r,std::strtok中的一個(gè)可重入的變量,它用一個(gè)額外的char**參數(shù)來(lái)代替靜態(tài)數(shù)據(jù)。這種方法很簡(jiǎn)單,而且提供了可能的最佳效果。但是這樣必須改變公共接口,也就意味著必須改代碼。另一種方法不用改變公有接口,而是用本地存儲(chǔ)線(xiàn)程(thread local storage)來(lái)代替靜態(tài)數(shù)據(jù)(有時(shí)也被成為特殊線(xiàn)程存儲(chǔ),thread-specific storage)。
Boost線(xiàn)程庫(kù)提供了智能指針boost::thread_specific_ptr來(lái)訪(fǎng)問(wèn)本地存儲(chǔ)線(xiàn)程。每一個(gè)線(xiàn)程第一次使用這個(gè)智能指針的實(shí)例時(shí),它的初值是NULL,所以必須要先檢查這個(gè)它的只是否為空,并且為它賦值。Boost線(xiàn)程庫(kù)保證本地存儲(chǔ)線(xiàn)程中保存的數(shù)據(jù)會(huì)在線(xiàn)程結(jié)束后被清除。
List5是一個(gè)使用boost::thread_specific_ptr的簡(jiǎn)單例子。其中創(chuàng)建了兩個(gè)線(xiàn)程來(lái)初始化本地存儲(chǔ)線(xiàn)程,并有10次循環(huán),每一次都會(huì)增加智能指針指向的值,并將其輸出到std::cout上(由于std::cout是一個(gè)共享資源,所以通過(guò)互斥體進(jìn)行同步)。main線(xiàn)程等待這兩個(gè)線(xiàn)程結(jié)束后就退出。從這個(gè)例子輸出可以明白的看出每個(gè)線(xiàn)程都處理屬于自己的數(shù)據(jù)實(shí)例,盡管它們都是使用同一個(gè)boost::thread_specific_ptr。
例5:
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/tss.hpp>
#include <iostream>
boost::mutex io_mutex;
boost::thread_specific_ptr<int> ptr;
struct count
{
count(int id) : id(id) { }
void operator()()
{
if (ptr.get() == 0)
ptr.reset(new int(0));
for (int i = 0; i < 10; ++i)
{
(*ptr)++;
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": "
<< *ptr << std::endl;
}
}
int id;
};
int main(int argc, char* argv[])
{
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
return 0;
}
還有一個(gè)問(wèn)題沒(méi)有解決:如何使得初始化工作(比如說(shuō)構(gòu)造函數(shù))也是線(xiàn)程安全的。比方說(shuō),如果一個(gè)引用程序要產(chǎn)生唯一的全局的對(duì)象,由于實(shí)例化順序的問(wèn)題,某個(gè)函數(shù)會(huì)被調(diào)用來(lái)返回一個(gè)靜態(tài)的對(duì)象,它必須保證第一次被調(diào)用時(shí)就產(chǎn)生這個(gè)靜態(tài)的對(duì)象。這里的問(wèn)題就是如果多個(gè)線(xiàn)程同時(shí)調(diào)用了這個(gè)函數(shù),那么這個(gè)靜態(tài)對(duì)象的構(gòu)造函數(shù)就會(huì)被調(diào)用多次,這樣錯(cuò)誤產(chǎn)生了。
解決這個(gè)問(wèn)題的方法就是所謂的“一次實(shí)現(xiàn)”(once routine)。“一次實(shí)現(xiàn)”在一個(gè)應(yīng)用程序只能執(zhí)行一次。如果多個(gè)線(xiàn)程想同時(shí)執(zhí)行這個(gè)操作,那么真正執(zhí)行的只有一個(gè),而其他線(xiàn)程必須等這個(gè)操作結(jié)束。為了保證它只被執(zhí)行一次,這個(gè)routine由另一個(gè)函數(shù)間接的調(diào)用,而這個(gè)函數(shù)傳給它一個(gè)指針以及一個(gè)標(biāo)志著這個(gè)routine是否已經(jīng)被調(diào)用的特殊標(biāo)志。這個(gè)標(biāo)志是以靜態(tài)的方式初始化的,這也就保證了它在編譯期間就被初始化而不是運(yùn)行時(shí)。因此也就沒(méi)有多個(gè)線(xiàn)程同時(shí)將它初始化的問(wèn)題了。Boost線(xiàn)程庫(kù)提供了boost::call_once來(lái)支持“一次實(shí)現(xiàn)”,并且定義了一個(gè)標(biāo)志boost::once_flag及一個(gè)初始化這個(gè)標(biāo)志的宏BOOST_ONCE_INIT。
List6是一個(gè)使用了boost::call_once的例子。其中定義了一個(gè)靜態(tài)的全局整數(shù),初始值為0;還有一個(gè)由BOOST_ONCE_INIT初始化的靜態(tài)boost::once_flag實(shí)例。main函數(shù)創(chuàng)建了兩個(gè)線(xiàn)程,它們都想通過(guò)傳入一個(gè)函數(shù)調(diào)用boost::call_once來(lái)初始化這個(gè)全局的整數(shù),這個(gè)函數(shù)是將它加1。main函數(shù)等待著兩個(gè)線(xiàn)程結(jié)束,并將最后的結(jié)果輸出的到std::cout。由最后的結(jié)果可以看出這個(gè)操作確實(shí)只被執(zhí)行了一次,因?yàn)樗闹凳?。
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <iostream>
int i = 0;
boost::once_flag flag =
BOOST_ONCE_INIT;
void init()
{
++i;
}
void thread()
{
boost::call_once(&init, flag);
}
int main(int argc, char* argv[])
{
boost::thread thrd1(&thread);
boost::thread thrd2(&thread);
thrd1.join();
thrd2.join();
std::cout << i << std::endl;
return 0;
}
Boost線(xiàn)程庫(kù)正在計(jì)劃加入一些新特性。其中包括boost::read_write_mutex,它可以讓多個(gè)線(xiàn)程同時(shí)從共享區(qū)中讀取數(shù)據(jù),但是一次只可能有一個(gè)線(xiàn)程向共享區(qū)寫(xiě)入數(shù)據(jù);boost::thread_barrier,它使得一組線(xiàn)程處于等待狀態(tài),知道所有得線(xiàn)程都都進(jìn)入了屏障區(qū);boost::thread_pool,他允許執(zhí)行一些小的routine而不必每一都要?jiǎng)?chuàng)建或是銷(xiāo)毀一個(gè)線(xiàn)程。
Boost線(xiàn)程庫(kù)已經(jīng)作為標(biāo)準(zhǔn)中的類(lèi)庫(kù)技術(shù)報(bào)告中的附件提交給C++標(biāo)準(zhǔn)委員會(huì),它的出現(xiàn)也為下一版C++標(biāo)準(zhǔn)吹響了第一聲號(hào)角。委員會(huì)成員對(duì)Boost線(xiàn)程庫(kù)的初稿給予了很高的評(píng)價(jià),當(dāng)然他們還會(huì)考慮其他的多線(xiàn)程庫(kù)。他們對(duì)在C++標(biāo)準(zhǔn)中加入對(duì)多線(xiàn)程的支持非常感興趣。從這一點(diǎn)上也可以看出,多線(xiàn)程在C++中的前途一片光明。
- The Boost.Threads Library by Bill Kempf
- Visit the Boost website at <http://www.boost.org>.
更多查看: