Ice笔记--C++线程与并发(小结)

来源:互联网 发布:历史优化必修一答案 编辑:程序博客网 时间:2024/06/05 05:03
   C++线程与并发(Ice3.4.2)

概述

Ice服务器是多线程模型的。在涉及资源的访问和操作的时候将要考虑同步访问机制。

Ice线程库提供了一些与线程有关的抽象:

互斥体,递归互斥体,读写递归互斥体,监控器,一个线程抽象,允许开发者创建,控制,销毁线程。

 

1.互斥体(The Mutex Class)

1.1)互斥体的定义

IceUtil::Mutex类提供了简单的非递归互斥机制,其定义如下:

[cpp] view plain copy
  1. namespaceIceUtil {  
  2.   
  3. enum MutexProtocol { PrioInherit, PrioNone };  
  4.   
  5. class Mutex {  
  6. public:  
  7.   
  8.         Mutex();  
  9.   
  10.         Mutex(MutexProtocol p);  
  11.         ~Mutex();  
  12.   
  13.         void lock() const/*lock 函数尝试获取互斥体。如果互斥体已经锁住,它就会挂起发出调用的线程(calling thread),直到互斥体变得可用为止*/  
  14.   
  15.         bool tryLock() const;/*trylock函数尝试获取互斥体。如果互斥体未被锁住则返回true,否则直接返回false*/  
  16.         void unlock() const;   /*尝试解除互斥体的加锁*/  
  17.   
  18.         typedef LockT<Mutex> Lock;  
  19.         typedef TryLockT<Mutex>TryLock;  
  20.   
  21. };  


 

1.2)使用互斥类

假设有一个FileSystem类和write的函数如下:

[cpp] view plain copy
  1. #include<IceUtil/Mutex.h>  
  2.   
  3. namespaceFilesystem {  
  4.   
  5.   class FileI : virtual public File,  
  6.             virtual public Filesystem::NodeI {  
  7.   public:  
  8.             // ...  
  9.   private:  
  10.             Lines _lines;  
  11.             IceUtil::Mutex _fileMutex;   //互斥锁  
  12.   };  
  13.   // ...  
  14. }  
  15.   
  16. void Filesystem::FileI::write(const Filesystem::Lines &text,const Ice::Current &)  
  17. {  
  18.   _fileMutex.lock();  
  19.   _lines = text;  
  20. //if(somecondition)return ;  
  21.   _fileMutex.unlock();  
  22. }  

      然而这种加入互斥机制的方法并不好,例如对互斥体加锁了但在函数返回时并没有实现解锁操作,这种情况下就引发死锁情况。

      因此我们建议使用Ice提供的两个助手类Lock和TryLock,如下:

[cpp] view plain copy
  1. voidSomeClass::someFunction(/* params here... */)  
  2. {  
  3.        IceUtil::Mutex::Locklock(_mutex); // 对mutex对象加锁  
  4.         // Lots of complexcode here...  
  5.        if (someCondition) {  
  6.             return;       // No problem  
  7.        }  
  8.        //...  
  9. // 此处调用Mutex类对象的析构函数,同时会解除互斥锁的加锁状态。  

2.递归互斥体(The C++ RecMutex Class)

上面所介绍的互斥体是非递归性质的,也就是说他们不能被多次加锁,即使是已经拥有该所的线程也不行。这样会给一些情况带来不便

[cpp] view plain copy
  1. IceUtil::Mutex_mutex;  
  2.   
  3. void f1()  
  4. {  
  5.       IceUtil::Mutex::Lock lock(_mutex);  
  6.       // ...  
  7. }  
  8.   
  9. void f2()  
  10. {  
  11.     IceUtil::Mutex::Locklock(_mutex);  
  12.     f1();    // Deadlock!  
  13.     // ...  
  14. }  

         为了解决这个问题,Ice同样也提供了递归互斥锁,如下示例:

[cpp] view plain copy
  1. #include <IceUtil/RecMutex.h>  
  2.   
  3. IceUtil::RecMutex _mutex; // Recursive mutex  
  4.   
  5. void f1()  
  6. {  
[cpp] view plain copy
  1.        IceUtil::RecMutex::Lock lock(_mutex);   //如果该互斥体已被其他线程加锁,那么该线程将会被挂起  
  2.         // ...  
  3. }  
  4.   
  5. void f2()  
  6. {  
  7.        IceUtil::RecMutex::Lock lock(_mutex);  
  8.        f1(); // Fine  
  9.        //...  
  10. }  
  11.     

3. 读写递归互斥体(The RWRecMutex Class)

由于递归互斥体无论是在读取还是写操作的情况下,都是将其并发线程访问序列化。但是读取资源的线程并不会修改所访问的内容;因此让多个读取线程并行拥有互斥体,而同一时刻只能有一个写入的线程获取互斥体。

下面是该读写互斥类的定义:

[cpp] view plain copy
  1. namespaceIceUtil {  
  2.       class RWRecMutex {  
  3.       public:  
  4.                void readLock() const;  
  5.                bool tryReadLock() const;  
  6.                bool timedReadLock(const Time&) const;  
  7.   
  8.                void writeLock() const;  
  9.                bool tryWriteLock() const;  
  10.                bool timedWriteLock(const Time&) const;  
  11.   
  12.                void unlock() const;  
  13.                void upgrade() const;  
  14.                bool timedUpgrade(const Time&) const;  
  15.   
  16.                typedef RLockT<RWRecMutex>RLock;  
  17.                typedefTryRLockT<RWRecMutex> TryRLock;  
  18.                typedef WLockT<RWRecMutex>WLock;  
  19.                typedefTryWLockT<RWRecMutex> TryWLock;  
  20.       };  
  21. }  

4.定时锁

读写锁提供了一些可使用超时的成员函数。等待的时间量是通过IceUtil::Time类的实例指定的。

5.监控器(The Monitor)

     5.1 Monitor类定义

       Monitor类在IceUtil::Monitor中定义,如下所示:

[cpp] view plain copy
  1.      namespace IceUtil {  
  2.          template <class T>  
  3.          class Monitor {  
  4.          public:  
  5.                    void lock() const;  
  6.                    void unlock() const;  
  7.                    bool tryLock() const;  
  8.   
  9.                    void wait() const;  
  10.                    bool timedWait(constTime&) const//这个函数挂起调用它的线程,直到指定的时间流逝.如果在超时之前唤醒被挂起的线程,  
  11.   
  12.                                                                                     //这个调用就返回true;否则返回false。  
  13.                       void notify();  
  14.                    void notifyAll();  
  15.   
  16.                    typedefLockT<Monitor<T> > Lock;  
  17.                    typedefTryLockT<Monitor<T> > TryLock;  
  18.          };  
  19. }  
  20.   
  21.    

    Monitor类相对于互斥体来说,它提供的互斥机制更为灵活,因为他们允许线程检查某一条件,如果条件为假,就让自己休眠;而这线程会让其他某个改变了条件状态的线程唤醒。

   关于如何使用该Monitor类,可以参考上一篇文章--C++线程与并发(二)。