IceUtil::Monitor类
namespace IceUtil { template <class T> class Monitor { public: void lock() const; void unlock() const; bool tryLock() const; void wait() const; bool timedWait(const Time&) const; void notify(); void notifyAll(); typedef LockT<Monitor<T> > Lock; typedef TryLockT<Monitor<T> > TryLock; }; }
1. 从代码可以看出,Monitor比Mutex(互斥体)多了wait/timedWait,notify/notifyAll操作。这样允许一个获得锁进入临界区的线程,能够自我挂起,让出临界区。
2.Monitor是个模板类,需要Mutex/RecMutex(递归互斥体)做为模板参数。
3.wait/timedWait在等待期间,会挂起线程,让出互斥体,等待被唤醒。
区别是:
timedWait(const Time&)会在时间到达后,自我唤醒,重新尝试获得锁;
wait()是等待被唤醒(其他线程调用notify()或者notifyAll()。
timedWait返回值:如果有另外的线程调用 notify 或 notifyAll,在发生超时之前唤醒挂起的线程,这个调用返回 true,监控器重被锁住,挂起的线程恢复执行。而如果发生超时,函数返回 false。
使用实例
template<class T> class Queue : public IceUtil::Monitor<IceUtil::Mutex> { public: void put(const T & item) { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); _q.push_back(item); notify(); } T get() { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); while (_q.size() == 0) wait(); T item = _q.front(); _q.pop_front(); return item; } private: list<T> _q; };
timedWait:时间到达后,尝试获取锁,但可能其他线程正在使用,当锁被释放时,才会真正得到,开始后续的执行。
..... IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); if ( queue_.empty() || queue_.size() < buffer_size_ ) { IceUtil::Time time = IceUtil::Time::seconds( 10 );//等待10s timedWait(time); } ...
补:
Mutex为简单互斥体:一个线程获得锁后,不能再尝试获得锁。
RecMutex为递归互斥体,一个线程可以多次尝试获得锁。