天天看點

Ice筆記--C++線程與并發(小結)

C++線程與并發(Ice3.4.2)

概述

Ice伺服器是多線程模型的。在涉及資源的通路和操作的時候将要考慮同步通路機制。

Ice線程庫提供了一些與線程有關的抽象:

互斥體,遞歸互斥體,讀寫遞歸互斥體,監控器,一個線程抽象,允許開發者建立,控制,銷毀線程。

1.互斥體(The Mutex Class)

1.1)互斥體的定義

IceUtil::Mutex類提供了簡單的非遞歸互斥機制,其定義如下:

[cpp]

​​ view plain​​

​​ copy​​

  1. namespaceIceUtil {  
  2. enum
  3. class
  4. public:  
  5.         Mutex();  
  6.         Mutex(MutexProtocol p);  
  7.         ~Mutex();  
  8. void lock() const; /*lock 函數嘗試擷取互斥體。如果互斥體已經鎖住,它就會挂起發出調用的線程(calling thread),直到互斥體變得可用為止*/
  9. bool tryLock() const;/*trylock函數嘗試擷取互斥體。如果互斥體未被鎖住則傳回true,否則直接傳回false*/
  10. void unlock() const;   /*嘗試解除互斥體的加鎖*/
  11. typedef
  12. typedef
  13. };  

1.2)使用互斥類

假設有一個FileSystem類和write的函數如下:

[cpp]

​​ view plain​​

​​ copy​​

  1. #include<IceUtil/Mutex.h>
  2. namespaceFilesystem {  
  3. class FileI : virtual public
  4. virtual public
  5. public:  
  6. // ...
  7. private:  
  8.             Lines _lines;  
  9. //互斥鎖
  10.   };  
  11. // ...
  12. }  
  13. void Filesystem::FileI::write(const Filesystem::Lines &text,const
  14. {  
  15.   _fileMutex.lock();  
  16.   _lines = text;  
  17. //if(somecondition)return ;
  18.   _fileMutex.unlock();  
  19. }  

      然而這種加入互斥機制的方法并不好,例如對互斥體加鎖了但在函數傳回時并沒有實作解鎖操作,這種情況下就引發死鎖情況。

      是以我們建議使用Ice提供的兩個助手類Lock和TryLock,如下:

[cpp]

​​ view plain​​

​​ copy​​

  1. voidSomeClass::someFunction(/* params here... */)  
  2. {  
  3. // 對mutex對象加鎖
  4. // Lots of complexcode here...
  5. if
  6. return;       // No problem
  7.        }  
  8. //...
  9. } // 此處調用Mutex類對象的析構函數,同時會解除互斥鎖的加鎖狀态。

2.遞歸互斥體(The C++ RecMutex Class)

上面所介紹的互斥體是非遞歸性質的,也就是說他們不能被多次加鎖,即使是已經擁有該所的線程也不行。這樣會給一些情況帶來不便

[cpp]

​​ view plain​​

​​ copy​​

  1. IceUtil::Mutex_mutex;  
  2. void
  3. {  
  4.       IceUtil::Mutex::Lock lock(_mutex);  
  5. // ...
  6. }  
  7. void
  8. {  
  9.     IceUtil::Mutex::Locklock(_mutex);  
  10. // Deadlock!
  11. // ...
  12. }  

         為了解決這個問題,Ice同樣也提供了遞歸互斥鎖,如下示例:

[cpp]

​​ view plain​​

​​ copy​​

  1. #include <IceUtil/RecMutex.h>
  2. IceUtil::RecMutex _mutex; // Recursive mutex
  3. void
  4. {  

[cpp]

​​ view plain​​

​​ copy​​

  1. //如果該互斥體已被其他線程加鎖,那麼該線程将會被挂起
  2. // ...
  3. }  
  4. void
  5. {  
  6.        IceUtil::RecMutex::Lock lock(_mutex);  
  7. // Fine
  8. //...
  9. }  

3. 讀寫遞歸互斥體(The RWRecMutex Class)

由于遞歸互斥體無論是在讀取還是寫操作的情況下,都是将其并發線程通路序列化。但是讀取資源的線程并不會修改所通路的内容;是以讓多個讀取線程并行擁有互斥體,而同一時刻隻能有一個寫入的線程擷取互斥體。

下面是該讀寫互斥類的定義:

[cpp]

​​ view plain​​

​​ copy​​

  1. namespaceIceUtil {  
  2. class
  3. public:  
  4. void readLock() const;  
  5. bool tryReadLock() const;  
  6. bool timedReadLock(const Time&) const;  
  7. void writeLock() const;  
  8. bool tryWriteLock() const;  
  9. bool timedWriteLock(const Time&) const;  
  10. void unlock() const;  
  11. void upgrade() const;  
  12. bool timedUpgrade(const Time&) const;  
  13. typedef
  14.                typedefTryRLockT<RWRecMutex> TryRLock;  
  15. typedef
  16.                typedefTryWLockT<RWRecMutex> TryWLock;  
  17.       };  
  18. }  

4.定時鎖

讀寫鎖提供了一些可使用逾時的成員函數。等待的時間量是通過IceUtil::Time類的執行個體指定的。

5.監控器(The Monitor)

     5.1 Monitor類定義

       Monitor類在IceUtil::Monitor中定義,如下所示:

[cpp]

​​ view plain​​

​​ copy​​

  1. namespace
  2. template <class
  3. class
  4. public:  
  5. void lock() const;  
  6. void unlock() const;  
  7. bool tryLock() const;  
  8. void wait() const;  
  9. bool timedWait(constTime&) const; //這個函數挂起調用它的線程,直到指定的時間流逝.如果在逾時之前喚醒被挂起的線程,
  10. //這個調用就傳回true;否則傳回false。
  11. void
  12. void
  13.                    typedefLockT<Monitor<T> > Lock;  
  14.                    typedefTryLockT<Monitor<T> > TryLock;  
  15.          };  
  16. }