造轮子之线程锁监控类的封装

线程锁监控类的封装

互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起配合使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步。

实现
/* 通常线程锁,都通过该类来使用,而不是直接用YR_ThreadMutex、YR_ThreadRecMutex 
 *  
 * 该类将YR_ThreadMutex/YR_ThreadRecMutex 与YR_ThreadCond结合起来; */

template <class T, class P>		//T为线程锁类型,P为线程条件类型
class YR_Monitor
{
public:

    /**
     * @brief 定义锁控制对象
     */
    typedef YR_LockT<TC_Monitor<T, P> > Lock;
    //typedef YR_TryLockT<TC_Monitor<T, P> > TryLock;

    /**
     * @brief 构造函数
     */
    YR_Monitor() : _nnotify(0)
    {
    }

    /**
     * @brief 析够
     */
    virtual ~YR_Monitor()
    {
    }

    /**
     * @brief 锁
     */
    void lock() const
    {
        _mutex.lock();
        _nnotify = 0;
    }

    /**
     * @brief 解锁, 根据上锁的次数通知
     */
    void unlock() const
    {
        notifyImpl(_nnotify);
        _mutex.unlock();
    }

    /**
     * @brief 尝试锁.
     *
     * @return bool
     */
    bool tryLock() const
    {
        bool result = _mutex.tryLock();
        if(result)
        {
            _nnotify = 0;
        }
        return result;
    }

    /**
     * @brief 等待,当前调用线程在锁上等待,直到事件通知,
     */
    void wait() const
    {
        notifyImpl(_nnotify);

        try
        {
            _cond.wait(_mutex);
        }
        catch(...)
        {
            _nnotify = 0;
            throw;
        }

        _nnotify = 0;
    }

    /**
     * @brief 等待时间,当前调用线程在锁上等待,直到超时或有事件通知
     *  
     * @param millsecond 等待时间
     * @return           false:超时了, ture:有事件来了
     */
    bool timedWait(int millsecond) const
    {
        notifyImpl(_nnotify);

        bool rc;

        try
        {
            rc = _cond.timedWait(_mutex, millsecond);
        }
        catch(...)
        {
            _nnotify = 0;
            throw;
        }

        _nnotify = 0;
        return rc;
    }

    /**
     * @brief 通知某一个线程醒来 
     *  
     * 通知等待在该锁上某一个线程醒过来 ,调用该函数之前必须加锁, 
     *  
     * 在解锁的时候才真正通知 
     */
    void notify()
    {
        if(_nnotify != -1)
        {
            ++_nnotify;
        }
    }

    /**
     * @brief 通知等待在该锁上的所有线程醒过来,
     * 注意调用该函数时必须已经获得锁.
     *  
     * 该函数调用前之必须加锁, 在解锁的时候才真正通知 
     */
    void notifyAll()
    {
        _nnotify = -1;
    }

protected:

    /**
     * @brief 通知实现. 
     *  
     * @param nnotify 上锁的次数
     */
    void notifyImpl(int nnotify) const
    {
        if(nnotify != 0)
        {
            if(nnotify == -1)
            {
                _cond.broadcast();
                return;
            }
            else
            {
                while(nnotify > 0)
                {
                    _cond.signal();
                    --nnotify;
                }
            }
        }
    }

private:
    YR_Monitor(const YR_Monitor&);
    void operator=(const YR_Monitor&);

protected:
    mutable int     _nnotify;	//上锁的次数
    mutable P       _cond;
    T               _mutex;
};

//普通线程锁
typedef YR_Monitor<YR_ThreadMutex, YR_ThreadCond> YR_ThreadLock;
//循环锁(一个线程可以加多次锁)
typedef YR_Monitor<YR_ThreadRecMutex, YR_ThreadCond> YR_ThreadRecLock;
}

这里互斥锁和条件变量的配合使用是下面的模式:

pthread_mutex_lock
...
pthread_cond_signal
pthread_mutex_unlock

原因:详见参考

参考

浅谈互斥锁为什么还要和条件变量配合使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值