C11:std::unique_lock和std::lock_guard的区别

在之前介绍了lock_guard的用法和作用.这里先简单的回顾下.

在这里我们用lock来管理m_mutex锁.当输出完毕后.lock的生命周期结束,则自动把m_mutex给unlock()解锁.用起来很方便.

std::mutex m_mutex;
void print(int cnt)
{
    std::lock_guard lock(m_mutex);
    cout << std::this_thread::get_id() << " " << cnt << endl;
}

不过他是在创建lock对象的时候.就已经把m_mutex给锁住了.且我们不能手动解锁.只能等生命周期消失才会自动解锁.这样的会就会出现一些问题..如果在一个函数方法中:需要保持线程安全的地方较多.总不能创建多个lock_guard对象把.这个时候我们可以使用unique_lock对象来进行锁的管理.

unique_lock对于锁的管理比较灵活.它不像lock_guard一样.必须要求他管理的锁在他初始化的时候必须加锁.而是可以自己灵活的.想加锁.就加锁.

std::mutex m_mutex;
void print(int cnt)
{
    //用unique_lock来对锁进行管理.defer_lock是它的构造参数之一.用来推迟加锁.
    unique_lock lock(m_mutex, defer_lock);
    /*
        ...这里可以进行一系列线程安全的操作...
    */
    //手动加锁.
    lock.lock();
    cout << std::this_thread::get_id() << " " << cnt << endl;
    lock.unlock();
    //这里用来计算sum的值.然后打印.因为sum是在函数内定义的局部变量.所以下面的代码是线程安全的.没必要用锁对这段代码进行保护.所以在上面用unlock解锁.
    int sum = 0;
    for (int i = 0; i < cnt; ++i)
    {
        sum += i;
    }
    //最后在手动加锁.不用手动释放.因为会在生命周期结束时自动释放.
    lock.lock();
    cout << std::this_thread::get_id() << " " << sum << endl;
}

注释了一堆.介绍了一堆.不如直接看源码来得直接:

unique_lock有很多的构造函数.主要看下面这个:
unique_lock(_Mutex& _Mtx, defer_lock_t) _NOEXCEPT
        : _Pmtx(&_Mtx), _Owns(false)
        {   
            //创建但并不加锁.
            // construct but don't lock
        }

加锁和解锁方式就是直接操作管理的mutex进行的.最后在析构函数中自动解锁.

// LOCK AND UNLOCK
void lock()
        {   // lock the mutex
        _Pmtx->lock();
        _Owns = true;
        }
void unlock()
        {   // unlock the mutex
        _Pmtx->unlock();
        _Owns = false;
        }
~unique_lock() _NOEXCEPT
        {   // clean up
        if (_Owns)
            _Pmtx->unlock();
        }

其中unique_lock和lock_guard还有一个区别:unique_lock对象是可以进行交换的.也就是说可以进行转移的.而lock_guard不行.

void swap(unique_lock& _Other) _NOEXCEPT
        {   // swap with _Other
        _STD swap(_Pmtx, _Other._Pmtx);
        _STD swap(_Owns, _Other._Owns);
        }
unique_lock& operator=(unique_lock&& _Other) _NOEXCEPT
        {   // destructive copy
        if (this != &_Other)
            {   // different, move contents
            if (_Owns)
                _Pmtx->unlock();
            _Pmtx = _Other._Pmtx;
            _Owns = _Other._Owns;
            _Other._Pmtx = 0;
            _Other._Owns = false;
            }
        return (*this);
        }

那么unique_lock和lock_guard两者应该如何去使用呢?到底使用哪个呢?unique_lock相对而言更加灵活.但是性能优越的东西,对于资源的消耗明显要大一些.而lock_guard虽然笨重一些,但是资源消耗相对要小一点.所以还是要看具体情况.

你可能感兴趣的:(C11)