造輪子之線程鎖的封裝

線程鎖的封裝

線程鎖的基本操作:

1. 創建鎖 int pthread_mutex_init(pthread_mutex_t*mutex, const pthread_mutexattr_t * attr);
    attr:創建鎖的屬性。一般默認爲NULL,分爲以下幾個屬性:
        * PTHREAD_MUTEX_TIMED_NP,這是缺省值,也就是普通鎖。當一個線程加鎖以後,其餘請求鎖的線程將形成一個等待隊列,並在解鎖後按優先級獲得鎖。這種鎖策略保證了資源分配的公平性;
        * PTHREAD_MUTEX_RECURSIVE_NP,嵌套鎖,允許同一個線程對同一個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭;
        * PTHREAD_MUTEX_ERRORCHECK_NP,檢錯鎖,如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同。這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖;
        * PTHREAD_MUTEX_ADAPTIVE_NP,適應鎖,動作最簡單的鎖類型,僅等待解鎖後重新競爭;
2. 加鎖 int pthread_mutex_lock(pthread_mutex_t*mutex);
3. 解鎖 int pthread_mutex_unlock(pthread_mutex_t *mutex);
4. 嘗試鎖 int pthread_mutex_trylock(pthread_mutex_t *mutex); //鎖被佔用返回EBUSY,而非等待
5. 鎖銷燬 int pthread_mutexattr_destroy (pthread_mutex_t *mutex);

線程鎖的封裝

線程鎖異常

struct YR_ThreadMutex_Exception : public YR_Lock_Exception
{
    YR_ThreadMutex_Exception(const string &buffer) : YR_Lock_Exception(buffer){};
    YR_ThreadMutex_Exception(const string &buffer, int err) : YR_Lock_Exception(buffer, err){};
    ~YR_ThreadMutex_Exception() throw() {};
};

線程鎖的定義

class YR_ThreadMutex
{
public:
	YR_ThreadMutex();
    virtual ~YR_ThreadMutex();
    //加鎖
    void lock() const;
    //解鎖
    void unlock() const;
    //嘗試鎖
    bool tryLock() const;
protected:
    mutable pthread_mutex_t _mutex;			//創建線程鎖
};

實現

鎖的初始化可以放在構造函數裏,這裏分爲四步來初始化線程鎖_mutex

YR_ThreadMutex::YR_ThreadMutex()
{
	int rc;
    pthread_mutexattr_t attr;					//1. 創建線程鎖屬性對象
    rc = pthread_mutexattr_init(&attr);			//初始化鎖屬性對象
    assert(rc == 0);
    
    //2. 將鎖屬性中的鎖類型設爲檢錯鎖
    rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
    assert(rc == 0);
    
    //3. 初始化鎖對象
    rc = pthread_mutex_init(&_mutex, &attr);
    assert(rc == 0);
    
    //4. 銷燬鎖屬性對象
    rc = pthread_mutexattr_destroy(&attr);
    assert(rc == 0);
    
    //如果操作不成功,則拋出異常
    if(rc != 0)
    {
        throw TC_ThreadMutex_Exception("[TC_ThreadMutex::TC_ThreadMutex] pthread_mutexattr_init error", rc);
    }
}

線程鎖在析構函數中銷燬:

YR_ThreadMutex::~YR_ThreadMutex()
{
    int rc = 0;
    rc = pthread_mutex_destroy(&_mutex);
    if(rc != 0)
    {
        cerr << "[YR_ThreadMutex::~YR_ThreadMutex] pthread_mutex_destroy error:" << string(strerror(rc)) << endl;
    }
}
加鎖
void YR_ThreadMutex::lock() const
{
    int rc = pthread_mutex_lock(&_mutex);
    if(rc != 0)
    {
        if(rc == EDEADLK)		//如果當前線程已經擁有線程鎖
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadMutex::lock] pthread_mutex_lock dead lock error", rc);
        }
        else
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadMutex::lock] pthread_mutex_lock error", rc);
        }
    }
}
解鎖
void YR_ThreadMutex::unlock() const
{
    int rc = pthread_mutex_unlock(&_mutex);
    if(rc != 0)
    {
        throw YR_ThreadMutex_Exception("[YR_ThreadMutex::unlock] pthread_mutex_unlock error", rc);
    }
}
嘗試鎖
bool YR_ThreadMutex::tryLock() const
{
    int rc = pthread_mutex_trylock(&_mutex);
    if(rc != 0 && rc != EBUSY)		//如果所佔用則返回EBUSY
    {
        if(rc == EDEADLK)			//如果當前線程已經擁有線程鎖
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadMutex::tryLock] pthread_mutex_trylock dead lock error", rc);
        }
        else
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadMutex::tryLock] pthread_mutex_trylock error", rc);
        }
    }
    return (rc == 0);
}

嵌套鎖的封裝

嵌套鎖的定義

class YR_ThreadRecMutex
{
public:
    /**
    * @brief 構造函數
    */
    YR_ThreadRecMutex();

    /**
    * @brief 析夠函數
    */
    virtual ~YR_ThreadRecMutex();

    /**
    * @brief 鎖, 調用pthread_mutex_lock. 
    *  
    * return : 返回pthread_mutex_lock的返回值
    */
    int lock() const;

    /**
    * @brief 解鎖, pthread_mutex_unlock. 
    *  
    * return : 返回pthread_mutex_lock的返回值
    */
    int unlock() const;

    /**
    * @brief 嘗試鎖, 失敗拋出異常. 
    *  
    * return : true, 成功鎖; false 其他線程已經鎖了
    */
    bool tryLock() const;
    /**
     * @brief 加鎖後調用unlock是否會解鎖, 給TC_Monitor使用的
     * 
     * @return bool
     */
    bool willUnlock() const;
protected:
    /**
     * @brief 友元類
     */
    friend class TC_ThreadCond;

    /**
     * @brief 計數
     */
    int count() const;

    /**
     * @brief 計數
     */
    void count(int c) const;
private:
    /**
    鎖對象
    */
    mutable pthread_mutex_t _mutex;
    mutable int _count;
};

實現

YR_ThreadRecMutex::YR_ThreadRecMutex()
: _count(0)
{
    int rc;

    pthread_mutexattr_t attr;
    //1. 線程屬性的初始化
    rc = pthread_mutexattr_init(&attr);
    if(rc != 0)
    {
        throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_init error", rc);
    }
    //2. 設置線程鎖類型,PTHREAD_MUTEX_RECURSIVE爲嵌套鎖
    rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    if(rc != 0)
    {
        throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_settype error", rc);
    }

    //3. 初始化線程
    rc = pthread_mutex_init(&_mutex, &attr);
    if(rc != 0)
    {
        throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutex_init error", rc);
    }

    //4. 銷燬線程屬性對象
    rc = pthread_mutexattr_destroy(&attr);
    if(rc != 0)
    {
        throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_destroy error", rc);
    }
}

YR_ThreadRecMutex::~YR_ThreadRecMutex()
{
    while (_count)
    {
        unlock();
    }

    int rc = 0;
    rc = pthread_mutex_destroy(&_mutex);			//銷燬線程
    if(rc != 0)
    {
        cerr << "[YR_ThreadRecMutex::~YR_ThreadRecMutex] pthread_mutex_destroy error:" << string(strerror(rc)) << endl;
    }
}
加鎖
int YR_ThreadRecMutex::lock() const
{
	int rc = pthread_mutex_lock(&_mutex);
    if(rc != 0)
    {
        //嵌套鎖不用判斷EDEADLK
        throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::lock] pthread_mutex_lock error",rc);
    }
    
    //只是計數加1,pthread_mutex_unlock避免鎖疊加
    if(++_count > 1)
    {
        rc = pthread_mutex_unlock(&_mutex);		
        assert(rc == 0);
    }
    return rc;
}
解鎖
int YR_ThreadRecMutex::unlock() const
{
    //當計數只有1的時候進行解鎖操作,大於1的情況只是計數減一即可
    if(--_count == 0)
    {
        int rc = 0;
        rc = pthread_mutex_unlock(&_mutex);
        return rc;
    }
    return 0;
}
嘗試鎖
bool YR_ThreadRecMutex::tryLock() const
{
    int rc = pthread_mutex_trylock(&_mutex);
    if(rc != 0 )
    {
        if(rc != EBUSY)
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::tryLock] pthread_mutex_trylock error", rc);
        }
    }
    else if(++_count > 1)
    {
        rc = pthread_mutex_unlock(&_mutex);
        if(rc != 0)
        {
            throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::tryLock] pthread_mutex_unlock error", rc);
        }
    }
    return (rc == 0);
}

計數
int YR_ThreadRecMutex::count() const
{
    int c   = _count;
    _count  = 0;
    return c;
}

void YR_ThreadRecMutex::count(int c) const
{
    _count = c;
}

unlock()之後是否會解鎖
bool YR_ThreadRecMutex::willUnlock() const
{
    return _count == 1;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章