除了thread,boost::thread另一個重要組成部分是mutex,以及工作在mutex上的boost::mutex::scoped_lock、condition和barrier,這些都是為實(shí)現(xiàn)線程同步提供的。
mutex
boost提供的mutex有6種:
boost::mutex
boost::try_mutex
boost::timed_mutex
boost::recursive_mutex
boost::recursive_try_mutex
boost::recursive_timed_mutex
下面僅對boost::mutex進(jìn)行分析。
mutex類是一個CriticalSection(臨界區(qū))封裝類,它在構(gòu)造函數(shù)中新建一個臨界區(qū)并InitializeCriticalSection,然后用一個成員變量
void* m_mutex;
來保存該臨界區(qū)結(jié)構(gòu)。
除 此之外,mutex還提供了do_lock、do_unlock等方法,這些方法分別調(diào)用EnterCriticalSection、 LeaveCriticalSection來修改成員變量m_mutex(CRITICAL_SECTION結(jié)構(gòu)指針)的狀態(tài),但這些方法都是private的,以防止我們直接對mutex進(jìn)行鎖操作,所有的鎖操作都必須通過mutex的友元類detail::thread::lock_ops<mutex>來完成,比較有意思的是,lock_ops的所有方法:lock、unlock、trylock等都是static的,如lock_ops<Mutex>::lock的實(shí)現(xiàn):
1、boost::thread的設(shè)計者不希望被我們直接操作mutex,改變其狀態(tài),所以mutex的所有方法都是private的(除了構(gòu)造函數(shù),析構(gòu)函數(shù))。
2、雖然我們可以通過lock_ops來修改mutex的狀態(tài),如:
scoped_lock
上面說過,不應(yīng)該直接用lock_ops來操作mutex對象,那么,應(yīng)該用什么呢?答案就是scoped_lock。與存在多種mutex一樣,存在多種與mutex對應(yīng)的scoped_lock:
scoped_lock
scoped_try_lock
scoped_timed_lock
這里我們只討論scoped_lock。
scoped_lock是定義在namespace boost::detail::thread下的,為了方便我們使用(也為了方便設(shè)計者),mutex使用了下面的typedef:
typedef detail::thread::scoped_lock<mutex> scoped_lock;
這樣我們就可以通過:
boost::mutex::scoped_lock
來使用scoped_lock類模板了。
由于scoped_lock的作用僅在于對mutex加鎖/解鎖(即使mutex EnterCriticalSection/LeaveCriticalSection),因此,它的接口也很簡單,除了構(gòu)造函數(shù)外,僅有l(wèi)ock/unlock/locked(判斷是否已加鎖),及類型轉(zhuǎn)換操作符void*,一般我們不需要顯式調(diào)用這些方法,因?yàn)閟coped_lock的構(gòu)造函數(shù)是這樣定義的:
注:m_mutex是一個mutex的引用。
因此,當(dāng)我們不指定initially_locked參數(shù)構(gòu)造一個scoped_lock對象 時,scoped_lock會自動對所綁定的mutex加鎖,而析構(gòu)函數(shù)會檢查是否加鎖,若已加鎖,則解鎖;當(dāng)然,有些情況下,我們可能不需要構(gòu)造時自動 加鎖,這樣就需要自己調(diào)用lock方法。后面的condition、barrier也會調(diào)用scoped_lock的lock、unlock方法來實(shí)現(xiàn)部 分方法。
正因?yàn)閟coped_lock具有可在構(gòu)造時加鎖,析構(gòu)時解鎖的特性,我們經(jīng)常會使用局部變量來實(shí)現(xiàn)對mutex的獨(dú)占訪問。
在每次輸出信息時,為了防止整個輸出過程被其它線程打亂,通過對io_mutex加鎖(進(jìn)入臨界區(qū)),從而保證了輸出的正確性。
在使用 scoped_lock時,我們有時候需要使用全局鎖(定義一個全局mutex,當(dāng)需要獨(dú)占訪問全局資源時,以該全局mutex為參數(shù)構(gòu)造一個 scoped_lock對象即可。全局mutex可以是全局變量,也可以是類的靜態(tài)方法等),有時候則需要使用對象鎖(將mutex定義成類的成員變 量),應(yīng)該根據(jù)需要進(jìn)行合理選擇。
Java的synchronized可用于對方法加鎖,對代碼段加鎖,對對象加鎖,對類加鎖(仍然是對象級 的),這幾種加鎖方式都可以通過上面講的對象鎖來模擬;相反,在Java中實(shí)現(xiàn)全局鎖好像有點(diǎn)麻煩,必須將請求封裝到類中,以轉(zhuǎn)換成上面的四種 synchronized形式之一。
condition
condition的接口如下:
其中wait用于等待某個condition的發(fā)生,而timed_wait則提供具有超時的wait功能,notify_one用于喚醒一個等待該condition發(fā)生的線程,notify_all則用于喚醒所有等待該condition發(fā)生的線程。
由于condition的語義相對較為復(fù)雜,它的實(shí)現(xiàn)也是整個boost::thread庫中最復(fù)雜的(對Windows版本而言,對支持pthread的版本而言,由于pthread已經(jīng)提供了pthread_cond_t,使得condition實(shí)現(xiàn)起來也十分簡單),下面對wait和notify_one進(jìn)行簡要分析。
condition內(nèi)部包含了一個condition_impl對象,由該對象執(zhí)行來處理實(shí)際的wait、notify_one...等操作。
mutex
boost提供的mutex有6種:
boost::mutex
boost::try_mutex
boost::timed_mutex
boost::recursive_mutex
boost::recursive_try_mutex
boost::recursive_timed_mutex
下面僅對boost::mutex進(jìn)行分析。
mutex類是一個CriticalSection(臨界區(qū))封裝類,它在構(gòu)造函數(shù)中新建一個臨界區(qū)并InitializeCriticalSection,然后用一個成員變量
void* m_mutex;
來保存該臨界區(qū)結(jié)構(gòu)。
除 此之外,mutex還提供了do_lock、do_unlock等方法,這些方法分別調(diào)用EnterCriticalSection、 LeaveCriticalSection來修改成員變量m_mutex(CRITICAL_SECTION結(jié)構(gòu)指針)的狀態(tài),但這些方法都是private的,以防止我們直接對mutex進(jìn)行鎖操作,所有的鎖操作都必須通過mutex的友元類detail::thread::lock_ops<mutex>來完成,比較有意思的是,lock_ops的所有方法:lock、unlock、trylock等都是static的,如lock_ops<Mutex>::lock的實(shí)現(xiàn):
1 template <typename Mutex>
2 class lock_ops : private noncopyable
3 {
4
5 public:
6 static void lock(Mutex& m)
7 {
8 m.do_lock();
9 }
10
11 }
boost::thread的設(shè)計者為什么會這么設(shè)計呢?我想大概是:2 class lock_ops : private noncopyable
3 {
4

5 public:
6 static void lock(Mutex& m)
7 {
8 m.do_lock();
9 }
10

11 }
1、boost::thread的設(shè)計者不希望被我們直接操作mutex,改變其狀態(tài),所以mutex的所有方法都是private的(除了構(gòu)造函數(shù),析構(gòu)函數(shù))。
2、雖然我們可以通過lock_ops來修改mutex的狀態(tài),如:
1 #include <boost/thread/thread.hpp>
2 #include <boost/thread/mutex.hpp>
3 #include <boost/thread/detail/lock.hpp>
4
5 int main()
6 {
7 boost::mutex mt;
8 //mt.do_lock(); // Error! Can not access private member!
9
10 boost::detail::thread::lock_ops<boost::mutex>::lock(mt);
11
12 return 0;
13 }
但是,這是不推薦的,因?yàn)閙utex、scoped_lock、condition、barrier是一套完整的類系,它們是相互協(xié)同工作的,像上面這么操作沒有辦法與后面的幾個類協(xié)同工作。2 #include <boost/thread/mutex.hpp>
3 #include <boost/thread/detail/lock.hpp>
4
5 int main()
6 {
7 boost::mutex mt;
8 //mt.do_lock(); // Error! Can not access private member!
9
10 boost::detail::thread::lock_ops<boost::mutex>::lock(mt);
11
12 return 0;
13 }
scoped_lock
上面說過,不應(yīng)該直接用lock_ops來操作mutex對象,那么,應(yīng)該用什么呢?答案就是scoped_lock。與存在多種mutex一樣,存在多種與mutex對應(yīng)的scoped_lock:
scoped_lock
scoped_try_lock
scoped_timed_lock
這里我們只討論scoped_lock。
scoped_lock是定義在namespace boost::detail::thread下的,為了方便我們使用(也為了方便設(shè)計者),mutex使用了下面的typedef:
typedef detail::thread::scoped_lock<mutex> scoped_lock;
這樣我們就可以通過:
boost::mutex::scoped_lock
來使用scoped_lock類模板了。
由于scoped_lock的作用僅在于對mutex加鎖/解鎖(即使mutex EnterCriticalSection/LeaveCriticalSection),因此,它的接口也很簡單,除了構(gòu)造函數(shù)外,僅有l(wèi)ock/unlock/locked(判斷是否已加鎖),及類型轉(zhuǎn)換操作符void*,一般我們不需要顯式調(diào)用這些方法,因?yàn)閟coped_lock的構(gòu)造函數(shù)是這樣定義的:
1 explicit scoped_lock(Mutex& mx, bool initially_locked=true)
2 : m_mutex(mx), m_locked(false)
3 {
4 if (initially_locked) lock();
5 }
2 : m_mutex(mx), m_locked(false)
3 {
4 if (initially_locked) lock();
5 }
注:m_mutex是一個mutex的引用。
因此,當(dāng)我們不指定initially_locked參數(shù)構(gòu)造一個scoped_lock對象 時,scoped_lock會自動對所綁定的mutex加鎖,而析構(gòu)函數(shù)會檢查是否加鎖,若已加鎖,則解鎖;當(dāng)然,有些情況下,我們可能不需要構(gòu)造時自動 加鎖,這樣就需要自己調(diào)用lock方法。后面的condition、barrier也會調(diào)用scoped_lock的lock、unlock方法來實(shí)現(xiàn)部 分方法。
正因?yàn)閟coped_lock具有可在構(gòu)造時加鎖,析構(gòu)時解鎖的特性,我們經(jīng)常會使用局部變量來實(shí)現(xiàn)對mutex的獨(dú)占訪問。
1 #include <boost/thread/thread.hpp>
2 #include <boost/thread/mutex.hpp>
3 #include <iostream>
4
5 boost::mutex io_mutex;
6
7 void count() // worker function
8 {
9 for (int i = 0; i < 10; ++i)
10 {
11 boost::mutex::scoped_lock lock(io_mutex);
12 std::cout << i << std::endl;
13 }
14 }
15
16 int main(int argc, char* argv[])
17 {
18 boost::thread thrd1(&count);
19 boost::thread thrd2(&count);
20 thrd1.join();
21 thrd2.join();
22
23 return 0;
24 }
2 #include <boost/thread/mutex.hpp>
3 #include <iostream>
4
5 boost::mutex io_mutex;
6
7 void count() // worker function
8 {
9 for (int i = 0; i < 10; ++i)
10 {
11 boost::mutex::scoped_lock lock(io_mutex);
12 std::cout << i << std::endl;
13 }
14 }
15
16 int main(int argc, char* argv[])
17 {
18 boost::thread thrd1(&count);
19 boost::thread thrd2(&count);
20 thrd1.join();
21 thrd2.join();
22
23 return 0;
24 }
在每次輸出信息時,為了防止整個輸出過程被其它線程打亂,通過對io_mutex加鎖(進(jìn)入臨界區(qū)),從而保證了輸出的正確性。
在使用 scoped_lock時,我們有時候需要使用全局鎖(定義一個全局mutex,當(dāng)需要獨(dú)占訪問全局資源時,以該全局mutex為參數(shù)構(gòu)造一個 scoped_lock對象即可。全局mutex可以是全局變量,也可以是類的靜態(tài)方法等),有時候則需要使用對象鎖(將mutex定義成類的成員變 量),應(yīng)該根據(jù)需要進(jìn)行合理選擇。
Java的synchronized可用于對方法加鎖,對代碼段加鎖,對對象加鎖,對類加鎖(仍然是對象級 的),這幾種加鎖方式都可以通過上面講的對象鎖來模擬;相反,在Java中實(shí)現(xiàn)全局鎖好像有點(diǎn)麻煩,必須將請求封裝到類中,以轉(zhuǎn)換成上面的四種 synchronized形式之一。
condition
condition的接口如下:
1 class condition : private boost::noncopyable // Exposition only
2 {
3 public:
4 // construct/copy/destruct
5 condition();
6 ~condition();
7
8 // notification
9 void notify_one();
10 void notify_all();
11
12 // waiting
13 template<typename ScopedLock> void wait(ScopedLock&);
14 template<typename ScopedLock, typename Pred> void wait(ScopedLock&, Pred);
15 template<typename ScopedLock>
16 bool timed_wait(ScopedLock&, const boost::xtime&);
17 template<typename ScopedLock, typename Pred>
18 bool timed_wait(ScopedLock&, Pred);
19 };
2 {
3 public:
4 // construct/copy/destruct
5 condition();
6 ~condition();
7
8 // notification
9 void notify_one();
10 void notify_all();
11
12 // waiting
13 template<typename ScopedLock> void wait(ScopedLock&);
14 template<typename ScopedLock, typename Pred> void wait(ScopedLock&, Pred);
15 template<typename ScopedLock>
16 bool timed_wait(ScopedLock&, const boost::xtime&);
17 template<typename ScopedLock, typename Pred>
18 bool timed_wait(ScopedLock&, Pred);
19 };
其中wait用于等待某個condition的發(fā)生,而timed_wait則提供具有超時的wait功能,notify_one用于喚醒一個等待該condition發(fā)生的線程,notify_all則用于喚醒所有等待該condition發(fā)生的線程。
由于condition的語義相對較為復(fù)雜,它的實(shí)現(xiàn)也是整個boost::thread庫中最復(fù)雜的(對Windows版本而言,對支持pthread的版本而言,由于pthread已經(jīng)提供了pthread_cond_t,使得condition實(shí)現(xiàn)起來也十分簡單),下面對wait和notify_one進(jìn)行簡要分析。
condition內(nèi)部包含了一個condition_impl對象,由該對象執(zhí)行來處理實(shí)際的wait、notify_one...等操作。
typedef unique_lock<mutex> scoped_lock;
即unique_lock類模板對mutex類的實(shí)例化,于是我去找unique_lock的構(gòu)造函數(shù),也不能找到你定義的
“”“
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
”“”
這種形式的構(gòu)造式;或許是boost版本不同的問題?