ice中间件之Monitor

最近在学习ice中间件,对于有关monitor部分进行一下总结。

在各论坛,博客找了很多资料,都不是很详细,下面做一个总结。

(一)监控器 

       监控器是一种用于保护临界区的同步机制:和互斥体一样,同一时刻在临界区内,只能有一个线程在活动。但是,监控器允许你在临界区内挂起线程;这样,另一个线程就能进入临界区。第二个线程可以离开监控器 (从而解除监控器的加锁),或者在监控器内挂起自己;不管是哪一种情况,原来的线程都会被唤醒,继续在监控器内执行。

(二)Monitor类

        

namespace IceUtil
{

template 
class Monitor
{
public:

    typedef LockT > Lock;
    typedef TryLockT > TryLock;

    Monitor();
    ~Monitor();

    //
    // Note that lock/tryLock & unlock in general should not be used
    // directly. Instead use Lock & TryLock.
    //
    void lock() const;
    void unlock() const;
    bool tryLock() const;

    void wait() const;
    bool timedWait(const Time&) const;
    void notify();
    void notifyAll();
};
}

成员函数:

• lock
尝试锁住监视器。如果监视器已被另外的线程锁住,线程就会挂起,直到监视器可用为止。在调用返回时,监视器已被锁住。

• tryLock
尝试锁住监视器。如果能够锁住监视器就返回true。如果监视器已被另外的线程锁住,返回false。

• unlock
解除监视器的加锁。如果有另外的线程在等待进入监视器(也就是阻塞在lock 调用中),其中一个线程会被唤醒,并锁住监控器。

• wait
挂起发出调用的线程,同时释放监视器上的锁。其他线程可以调用notify 或notifyAll 来唤醒在wait调用中挂起的线程。当wait 调用返回时,监视器重新被锁住,而挂起的线程会恢复执行。

• timedWait
挂起发出调用的线程,直到到达指定的超时值。如果有另外的线程调用notify 或notifyAll,在发生超时之前唤醒挂起的线程,这个调用返回true,监视器重新被锁住,挂起的线程恢复执行。如果发生超时,函数返回false。

• notify
这个函数唤醒目前在wait 调用中挂起的一个线程。如果在调用notify 时没有这样的线程,通知就会丢弃。

发出通知不会导致另外的线程立即运行。只有当发出通知的线程调用wait或timedWait或解锁监视器时,另外的线程才会得以运行。

• notifyAll
唤醒目前在wait 调用中挂起的所有线程。和notify一样,如果这时没有挂起的线程,对notifyAll 的调用就会丢弃。

使用监视器必须遵守一些规则:
• 只有持有锁时,才能调用unlock。
• 只有持有锁时,才能调用wait或timedWait。
• 只有持有锁时,调用notify或notifyAll。
• 解锁次数必须与加锁次数相同。
• wait返回时,须要重新测试条件。

(三)理解 IceUtil::Monitor::Lock lock(_monitor); 

我们先看一下Lock类的内容:

template 
class LockT
{
public:
    
    LockT(const T& mutex) :
        _mutex(mutex)
    {
        _mutex.lock();
        _acquired = true;
    }

    ~LockT()
    {
        if (_acquired)
        {
            _mutex.unlock();
        }
    }
};
}

首先理解一个概念:

lock 的构造器针对互斥体调用 lock,使函数的余下部分都处在临界区中。剩下的代码段或者通过普通的方式返回,或者因为在在函数中有异常抛出而返回。不管函数是怎样终止的, C++ run time 都会解开栈,调用 lock 的析构器,从而解除互斥体的加锁,这样,我们就不会陷入死锁问题了

LockT类,也是一个模板类,我们主要关注构造函数 LockT(const T& mutex) :       

Monitor类,也是一个模板类,typedef LockT > Lock;

然后观察:

IceUtil::Monitor _monitor;  //对于LockT的  T

IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_monitor);  //对于Monitor的T

是不是理解了?

(四)实例

#include 

template 
class Queue: public IceUtil::Monitor 
{
public:
    void put(const T & item) 
    {
        IceUtil::Monitor::Lock lock(*this);
        _q.push_back(item);
        notify();
    }
    T get() 
    {
        IceUtil::Monitor::Lock lock(*this);
        while (_q.size() == 0)
        wait();
        T item = _q.front();
        _q.pop_front();
        return item;
}
private:
    list _q;
};

(五)总结

对于多个函数中都进行了锁监控器的操作,可以通俗理解为,每次只能在这些锁了的函数中选取一个进行操作。

monitor.wait()函数还是需要多理解一下的。

不能满足于会用,而是要知道是这么用的,所以我才花了整整一天的时间找资料,看源码,也希望能帮助到需要疑惑的人!

   

 

 

你可能感兴趣的:(ice中间件)