C++并发与多线程(三)unique_lock详解

1. unique_lock取代lock_guard

unique_lock 是一个类模板,其将一个互斥量与自身绑定,可以完全取代lock_guard

unique_lock myguard(mymutex) 等价于lock_guard myguard(mymutex)

相比于lock_guardunique_lock更加灵活,但在效率上差一点,内存占用上多一点。

2. unique_lock的第二个参数

adopt_lock

示例:unique_lock myguard(mymutex, adopt_lock)

作用:表明互斥量mymutex 已经被lock() 上了,不会在unique_lock的构造函数中调用mymutex.lock(),因此在使用这个参数前必须将互斥量上锁。

try_to_lock

示例:unique_lock myguard(mymutex, try_to_lock)

作用:尝试去锁上互斥量mymutex,如果没有锁上也不会在此处等待,而是立刻返回,因此在使用前不能将互斥量上锁。

void inMsgRecvQueue() {
        for (int i = 0; i < 10; ++i) {
            cout << "inMessageQueue执行,插入一个元素" << i << endl;
            unique_lock<mutex> myguard(mymutex, try_to_lock);
            //使用成员函数owns_lock()来 判断是否上锁成功
            if (myguard.owns_lock()){
                msgRecvQueue.push_back(i);
            } else {
                cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl;
            }
        }
    }

defer_lock

示例:unique_lock myguard(mymutex, defer_lock)

作用:初始化了一个没有加锁的互斥量,可以配合其成员函数灵活使用,因此在使用前不能将互斥量上锁。

void inMsgRecvQueue() {
        for (int i = 0; i < 10; ++i) {
            cout << "inMessageQueue执行,插入一个元素" << i << endl;
            unique_lock<mutex> myguard(mymutex1, defer_lock);
            myguard.lock();
            //开始处理共享数据1
            myguard.unlock();
            myguard.lock();
            //开始处理共享数据2
            if (myguard1.owns_lock()){
                msgRecvQueue.push_back(i);
            } else {
                cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl;
            } 
        }
    }

注意:如果在最后面给互斥量解锁了,在函数结束时,myguard 调用析构函数将不会执行mymutex.unlock()

3. unique_lock的成员函数

lock():给其绑定的互斥量上锁

unlock():给其绑定的互斥量解锁

try_lock():尝试给互斥量上锁,如果成功,返回True,否则返回False,此函数不会造成阻塞

void inMsgRecvQueue() {
        for (int i = 0; i < 10; ++i) {
            cout << "inMessageQueue执行,插入一个元素" << i << endl;
            unique_lock<mutex> myguard(mymutex, defer_lock);
            if (myguard.try_lock()){
                msgRecvQueue.push_back(i);
            } else {
                cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl;
            }
        }
    }

release()

返回它所绑定的mutex对象指针,并释放所有权,此后mymutexmyguard不再有关

如果原mutex 处于加锁状态,有责任在处理完后进行mutex.unlock() 操作

void inMsgRecvQueue() {
        for (int i = 0; i < 10; ++i) {
            cout << "inMessageQueue执行,插入一个元素" << i << endl;
            unique_lock<mutex> myguard(mymutex);
            mutex* p = myguard.release();
            msgRecvQueue.push_back(i);
            p->unlock();
        }
    }

4. unique_lock所有权的传递

unique_lock myguard(mymutex, defer_lock)

当一个unique_lock与一个mutex绑定后,unique_lock就拥有了mutex的所有权

所有权可以转移move()但不能复制,类似与智能指针unique_ptr

void inMsgRecvQueue() {
        for (int i = 0; i < 10; ++i) {
            cout << "inMessageQueue执行,插入一个元素" << i << endl;
            unique_lock<mutex> myguard1(mymutex);
            unique_lock<mutex> myguard2(move(myguard1));
            msgRecvQueue.push_back(i);
        }
    }

转移后myguard2 继承了myguard1所绑定的mutexmyguard1什么都不绑定。

你可能感兴趣的:(C++并发与多线程,c++,开发语言,后端)