C++线程锁封装

C++线程锁的封装,主要提供lock,unlock,require等操作,需要注意的是线程重复获取锁的问题,设置了一个count的计数器,该计算器之所以不考虑++,--的原子操作的问题,是因为该计数器本身就在lock与unlock中,所以本身是线程安全的。


另外mutable count是将count的变化操作防止在const方法中,保证方法语义。



class TC_ThreadCond;

/**
 * 线程互斥对象
 */
struct TC_ThreadMutex_Exception : public TC_Lock_Exception
{
    TC_ThreadMutex_Exception(const string &buffer) : TC_Lock_Exception(buffer){};
    TC_ThreadMutex_Exception(const string &buffer, int err) : TC_Lock_Exception(buffer, err){};
    ~TC_ThreadMutex_Exception() throw() {};
};

/**
* 线程锁
*/
class TC_ThreadMutex
{
public:

    TC_ThreadMutex();
    virtual ~TC_ThreadMutex();

    /**
     * 加锁
     */
    void lock() const;

    /**
     * 尝试锁
     * 
     * @return bool
     */
    bool tryLock() const;

    /**
     * 解锁
     */
    void unlock() const;

    /**
     * 加锁后调用unlock是否会解锁, 给TC_Monitor使用的
     * 永远返回true
     * 
     * @return bool
     */
    bool willUnlock() const { return true;}

protected:

    // noncopyable
    TC_ThreadMutex(const TC_ThreadMutex&);
    void operator=(const TC_ThreadMutex&);

	/**
     * 计数
	 */
    int count() const;

    /**
     * 计数
	 */
    void count(int c) const;

    friend class TC_ThreadCond;

protected:
    mutable pthread_mutex_t _mutex;

};

/**
* 线程锁类
* 采用线程库实现
**/
class TC_ThreadRecMutex
{
public:

    /**
    * 构造函数
    */
    TC_ThreadRecMutex();

    /**
    * 析够函数
    */
    virtual ~TC_ThreadRecMutex();

    /**
    * 锁, 调用pthread_mutex_lock
    * return : 返回pthread_mutex_lock的返回值
    */
    int lock() const;

    /**
    * 解锁, pthread_mutex_unlock
    * return : 返回pthread_mutex_lock的返回值
    */
    int unlock() const;

    /**
    * 尝试锁, 失败抛出异常
    * return : true, 成功锁; false 其他线程已经锁了
    */
    bool tryLock() const;

    /**
     * 加锁后调用unlock是否会解锁, 给TC_Monitor使用的
     * 
     * @return bool
     */
    bool willUnlock() const;
protected:

	/**
     * 友元类
     */
    friend class TC_ThreadCond;

	/**
     * 计数
	 */
    int count() const;

    /**
     * 计数
	 */
    void count(int c) const;

private:
    /**
    锁对象
    */
    mutable pthread_mutex_t _mutex;
	mutable int _count;
};


TC_ThreadMutex::TC_ThreadMutex()
{
    int rc;
    pthread_mutexattr_t attr;
    rc = pthread_mutexattr_init(&attr);
    assert(rc == 0);

    rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
    assert(rc == 0);

    rc = pthread_mutex_init(&_mutex, &attr);
    assert(rc == 0);

    rc = pthread_mutexattr_destroy(&attr);
    assert(rc == 0);

    if(rc != 0)
    {xxx
        throw TC_ThreadMutex_Exception("[TC_ThreadMutex::TC_ThreadMutex] pthread_mutexattr_init error", rc);
    }
}

TC_ThreadMutex::~TC_ThreadMutex()
{
    int rc = 0;
    rc = pthread_mutex_destroy(&_mutex);
    assert(rc == 0);
}

void TC_ThreadMutex::lock() const
{
    int rc = pthread_mutex_lock(&_mutex);
    if(rc != 0)
    {
        if(rc == EDEADLK)
    	{
            throw TC_ThreadMutex_Exception("[TC_ThreadMutex::lock] pthread_mutex_lock dead lock error", rc);
    	}
    	else
    	{
            throw TC_ThreadMutex_Exception("[TC_ThreadMutex::lock] pthread_mutex_lock error", rc);
    	}
    }
}

bool TC_ThreadMutex::tryLock() const
{
    int rc = pthread_mutex_trylock(&_mutex);
    if(rc != 0 && rc != EBUSY)
    {
        if(rc == EDEADLK)
    	{
            throw TC_ThreadMutex_Exception("[TC_ThreadMutex::tryLock] pthread_mutex_trylock dead lock error", rc);
    	}
    	else
    	{
            throw TC_ThreadMutex_Exception("[TC_ThreadMutex::tryLock] pthread_mutex_trylock error", rc);
    	}
    }
    return (rc == 0);
}

void TC_ThreadMutex::unlock() const
{
    int rc = pthread_mutex_unlock(&_mutex);
    if(rc != 0)
    {
        throw TC_ThreadMutex_Exception("[TC_ThreadMutex::unlock] pthread_mutex_unlock error", rc);
    }
}

int TC_ThreadMutex::count() const
{
    return 0;
}

void TC_ThreadMutex::count(int c) const
{
}

///
TC_ThreadRecMutex::TC_ThreadRecMutex()
: _count(0)
{
    int rc;

    pthread_mutexattr_t attr;
    rc = pthread_mutexattr_init(&attr);
    if(rc != 0)
    {
		throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::TC_ThreadRecMutex] pthread_mutexattr_init error", rc);
    }
    rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    if(rc != 0)
    {
		throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::TC_ThreadRecMutex] pthread_mutexattr_settype error", rc);
    }

    rc = pthread_mutex_init(&_mutex, &attr);
    if(rc != 0)
    {
		throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::TC_ThreadRecMutex] pthread_mutex_init error", rc);
    }

    rc = pthread_mutexattr_destroy(&attr);
    if(rc != 0)
    {
		throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::TC_ThreadRecMutex] pthread_mutexattr_destroy error", rc);
    }
}

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

    int rc = 0;
    rc = pthread_mutex_destroy(&_mutex);
    assert(rc == 0);
}

int TC_ThreadRecMutex::lock() const
{
    int rc = pthread_mutex_lock(&_mutex);
    if(rc != 0)
    {
		throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::lock] pthread_mutex_lock error", rc);
    }

    if(++_count > 1)
    {
		rc = pthread_mutex_unlock(&_mutex);
		assert(rc == 0);
    }

	return rc;
}

int TC_ThreadRecMutex::unlock() const
{
    if(--_count == 0)
    {
		int rc = 0;
		rc = pthread_mutex_unlock(&_mutex);
		return rc;
    }
	return 0;
}

bool TC_ThreadRecMutex::tryLock() const
{
    int rc = pthread_mutex_trylock(&_mutex);
    if(rc != 0 )
    {
		if(rc != EBUSY)
		{
			throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::tryLock] pthread_mutex_trylock error", rc);
		}
    }
    else if(++_count > 1)
    {
        rc = pthread_mutex_unlock(&_mutex);
        if(rc != 0)
        {
            throw TC_ThreadMutex_Exception("[TC_ThreadRecMutex::tryLock] pthread_mutex_unlock error", rc);
        }
    }
    return (rc == 0);
}

bool TC_ThreadRecMutex::willUnlock() const
{
    return _count == 1;
}

int TC_ThreadRecMutex::count() const
{
    int c   = _count;
    _count  = 0;
    return c;
}

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





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
hiredis是一个用于C语言的轻量级Redis客户端库。封装hiredis使其线程安全,需要考虑到在多线程环境下,访问Redis服务器可能产生的竞态条件和线程安全问题。 首先,可以通过使用互斥锁(mutex)来实现对hiredis的封装。在每个对Redis的操作函数(如连接、执行命令等)之前,对互斥锁进行加锁操作,以保证同一时间只有一个线程可以对hiredis进行操作。然后,在操作执行完成后,释放互斥锁,使其他线程可以获得对hiredis的访问权限。 其次,为了避免线程之间的竞态条件,可以引入线程安全的数据结构来存储和处理hiredis的请求和响应。例如,可以使用线程安全的队列来存储需要发送给Redis服务器的命令,以及用于存储接收到的响应的缓冲区。在对队列和缓冲区进行访问时,使用互斥锁进行保护,以确保线程之间的安全访问。 此外,还可以考虑使用条件变量(condition variable)来实现异步通知机制。当一个线程向Redis服务器发送了一个命令之后,它可以等待条件变量的通知,以便知道命令已经执行完毕并且可以获取到相应的结果。在命令执行完毕后,可以通过条件变量的通知机制来唤醒等待的线程,并将结果返回给相应的线程。 总之,封装hiredis使其线程安全需要引入互斥锁、线程安全的数据结构以及条件变量等机制,以确保在多线程环境下对Redis服务器的访问能够安全可靠地进行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值