死锁问题及分析

最近写了一个hiredis的连接池,借鉴了HiRedis库封装,加了些日志,发现这个在ReleaseClient函数中构造shared_ptr时,没有指定delete。修改后在项目使用过程中发现执行一段时间后总是是卡死,使用的是boost库中的锁及其条件变量。
而日志系统中也用到了锁,添加日志调用时无序的。
连接池中用的锁用lock1表示,日志系统中用的锁用lock2表示
就会出现线程1调用锁的顺序为lock1->lock2,而线程2调用锁的顺序为lock2->lock1,造成死锁
将日志调用去掉后,没有出现卡死情况了

typedef std::shared_ptr<RedisClient> RedisClientPtr;

class HiRedisPool
{
public:
    static HiRedisPool* getInstance()
    {
        static HiRedisPool instance;
        return &instance;
    }

    void init(const std::string& ip, int port, size_t maxCon);

    void getRedisClient(RedisClientPtr& redisClientPtr);

    void releaseClient(RedisClient *client_ptr);

    inline size_t size()
    {
        boost::lock_guard<boost::mutex> lock(_mutex);

        return _pool.size();
    }

    inline size_t used()
    {
        boost::lock_guard<boost::mutex> lock(_mutex);

        return _used;
    }

private:
    HiRedisPool();
    HiRedisPool(const HiRedisPool& other);
    HiRedisPool& operator=(const HiRedisPool& other);

private:
    std::string _ip;
    int _port;
    size_t _used;
    size_t _maxConnection;
    std::list<RedisClientPtr> _pool;
    boost::mutex _mutex;
    boost::condition_variable _cv;
};

HiRedisPool::HiRedisPool()
{

}

void HiRedisPool::init(const std::string& ip, int port, size_t maxCon)
{
    boost::lock_guard<boost::mutex> lock(_mutex);

    _ip = ip;
    _port = port;
    _maxConnection = maxCon;
    _used = 0;
}


void HiRedisPool::getRedisClient(RedisClientPtr& redisClientPtr)
{
    boost::unique_lock<boost::mutex> lock(_mutex);
    if (!_pool.empty()) {
        redisClientPtr = _pool.front();

        _pool.pop_front();

    } else if (_used < _maxConnection){
        ++_used;
        redisClientPtr = std::shared_ptr<RedisClient>(new RedisClient(_ip, _port),
                                                       std::bind(&HiRedisPool::releaseClient, this, std::placeholders::_1));
    } else {
        _cv.wait(lock, [this](){return !this->_pool.empty();});
        redisClientPtr = _pool.front();
        _pool.pop_front();
    }
}

void HiRedisPool::releaseClient(RedisClient *client_ptr)
{
    {
        boost::lock_guard<boost::mutex> lock(_mutex);

        _pool.push_back(std::shared_ptr<RedisClient>(client_ptr,
                                                      std::bind(&HiRedisPool::releaseClient, this, std::placeholders::_1)));
    }


    _cv.notify_one();

}

你可能感兴趣的:(C++,多线程同步)