C++多线程编程第六讲--unique_lock详解
//(1)unique_lock取代lock_guard,unique_lock是一个类模板,比lock_guard更加灵活。
// lock_guard取代了mutex的lock()和unlock()。unique_lock比lock_guard效率低一点,内存占用多一些。
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
using namespace std;
class A
{
public:
    //把收到的消息,入到一个队列中
    void inMsgRecvQueue()
    {
        int i;
        for (i = 0; i < 100000; ++i)
        {
            cout << "push_back num = " << i << endl;
            //lock之后只能有一个线程可以对msgQueue队列做操作
            //lock_guard<mutex> sbguard(my_mutex);
            unique_lock<mutex> my_unique_lock(my_mutex);
            msgQueue.push_back(i);                   //数字i就是玩家的命令。
        }
    }
    bool outMsgProc(int& command)
    {
        //lock_guard<mutex> sbguard(my_mutex);
        unique_lock<mutex> my_unique_lock(my_mutex);
        if (!msgQueue.empty())
        {
            //消息不为空
            command = msgQueue.front();
            msgQueue.pop_front();          //移除首元素
            return true;
        }
        else
        {
            return false;
        }
    }
    //把数据从消息队列中取出
    void outMsgRecvQueue()
    {
        int i;
        int command = 0;
        for (i = 0; i < 100000; ++i)
        {
            int result = outMsgProc(command);
            if (result == true)
            {
                cout << "command = " << command << endl;
            }
            else
            {
                cout << "msgQueue is empty" << endl;
            }
        }
    }
private:
    list<int> msgQueue;
    mutex my_mutex;       //创建一个互斥量
};
int main()
{
    A myobj;
    thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
    thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    myOutMsg.join();
    myInMsg.join();
    cout << "main thread end..." << endl;
    return 0;
} 
//(2)unique_lock的第二个参数
	//(2.1)std::adopt_lock,       表示mutex已经lock。
   #include<iostream>
    #include<thread>
    #include<vector>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class A
    {
    public:
        //把收到的消息,入到一个队列中
        void inMsgRecvQueue()
        {
            int i;
            for (i = 0; i < 100000; ++i)
            {
    
                cout << "push_back num = " << i << endl;
                //lock之后只能有一个线程可以对msgQueue队列做操作
                //lock_guard<mutex> sbguard(my_mutex);
                my_mutex.lock();      //要先lock
                unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
            }
        }
    
        bool outMsgProc(int& command)
        {
            //lock_guard<mutex> sbguard(my_mutex);
            my_mutex.lock();    //要先lock
            unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
    
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                return true;
            }
            else
            {
                return false;
            }
        }
    
        //把数据从消息队列中取出
        void outMsgRecvQueue()
        {
            int i;
            int command = 0;
            for (i = 0; i < 100000; ++i)
            {
                int result = outMsgProc(command);
                if (result == true)
                {
                    cout << "command = " << command << endl;
                }
                else
                {
                    cout << "msgQueue is empty" << endl;
                }
            }
        }
    
    private:
        list<int> msgQueue;
        mutex my_mutex;       //创建一个互斥量
    };
    
    int main()
    {
        A myobj;
        thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
        thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    
        myOutMsg.join();
        myInMsg.join();
    
        cout << "main thread end..." << endl;
        return 0;
    }
 //(2.2)std::try_to_lock, 尝试用mutex的lock去加锁,如果lock不成功,也会立即返回,并不会阻塞在这里。
    // 用之前不能在本线程中先lock。
#include<iostream>
    #include<thread>
    #include<vector>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class A
    {
    public:
        //把收到的消息,入到一个队列中
        void inMsgRecvQueue()
        {
            int i;
            for (i = 0; i < 100000; ++i)
            {
    
                cout << "push_back num = " << i << endl;
                //lock之后只能有一个线程可以对msgQueue队列做操作
                //lock_guard<mutex> sbguard(my_mutex);
                unique_lock<mutex> my_unique_lock(my_mutex, std::try_to_lock);
                if (my_unique_lock.owns_lock())
                {
                    msgQueue.push_back(i);                   //数字i就是玩家的命令。
                }
                else
                {
                    //没拿到锁做的事情
                    cout << "Do not have lock" << endl;
                }
    
            }
        }
    
        bool outMsgProc(int& command)
        {
            //lock_guard<mutex> sbguard(my_mutex);
            my_mutex.lock();    //要先lock
            unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
    
            std::chrono::milliseconds dura(2000);          //休息20秒
            std::this_thread::sleep_for(dura);
    
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                return true;
            }
            else
            {
                return false;
            }
        }
    
        //把数据从消息队列中取出
        void outMsgRecvQueue()
        {
            int i;
            int command = 0;
            for (i = 0; i < 100000; ++i)
            {
                int result = outMsgProc(command);
                if (result == true)
                {
                    cout << "command = " << command << endl;
                }
                else
                {
                    cout << "msgQueue is empty" << endl;
                }
            }
        }
    
    private:
        list<int> msgQueue;
        mutex my_mutex;       //创建一个互斥量
    };
    
    int main()
    {
        A myobj;
        thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
        thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    
        myOutMsg.join();
        myInMsg.join();
    
        cout << "main thread end..." << endl;
        return 0;
    }
 //(2.3)std::defer_lock 不能自己先lock,否则会报异常。初始化一个没有加锁的mutex
//(3)unique_lock的成员函数
	//(3.1)lock()                 手动加锁,配合std::defer_lock使用,但是不必显式的解锁。
	//(3.2)unlock()               解锁,可用于处理其他代码时的暂时解锁。
  #include<iostream>
    #include<thread>
    #include<vector>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class A
    {
    public:
        //把收到的消息,入到一个队列中
        void inMsgRecvQueue()
        {
            int i;
            for (i = 0; i < 100000; ++i)
            {
                cout << "push_back num = " << i << endl;
                //lock之后只能有一个线程可以对msgQueue队列做操作
                //lock_guard<mutex> sbguard(my_mutex);
                unique_lock<mutex> my_unique_lock(my_mutex, std::defer_lock);  //创建一个没有加锁的unique_lock
                my_unique_lock.lock();
                //处理共享代码...
    
                my_unique_lock.unlock();
                //处理非共享代码...
    
                my_unique_lock.lock();
    
                msgQueue.push_back(i);                   //数字i就是玩家的命令。     
            }
        }
    
        bool outMsgProc(int& command)
        {
            //lock_guard<mutex> sbguard(my_mutex);
            my_mutex.lock();    //要先lock
            unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
    
            std::chrono::milliseconds dura(2000);          //休息2秒
            std::this_thread::sleep_for(dura);
    
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                return true;
            }
            else
            {
                return false;
            }
        }
    
        //把数据从消息队列中取出
        void outMsgRecvQueue()
        {
            int i;
            int command = 0;
            for (i = 0; i < 100000; ++i)
            {
                int result = outMsgProc(command);
                if (result == true)
                {
                    cout << "command = " << command << endl;
                }
                else
                {
                    cout << "msgQueue is empty" << endl;
                }
            }
        }
    
    private:
        list<int> msgQueue;
        mutex my_mutex;       //创建一个互斥量
    };
    
    int main()
    {
        A myobj;
        thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
        thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
        myOutMsg.join();
        myInMsg.join();
        cout << "main thread end..." << endl;
    }
//(3.3)try_lock() 尝试给互斥量加锁
    #include<iostream>
    #include<thread>
    #include<vector>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class A
    {
    public:
        //把收到的消息,入到一个队列中
        void inMsgRecvQueue()
        {
            int i;
            for (i = 0; i < 100000; ++i)
            {
                cout << "push_back num = " << i << endl;
                //lock之后只能有一个线程可以对msgQueue队列做操作
                //lock_guard<mutex> sbguard(my_mutex);
                unique_lock<mutex> my_unique_lock(my_mutex, std::defer_lock);  //创建一个没有加锁的unique_lock
                if (my_unique_lock.try_lock() == true)
                {
                    msgQueue.push_back(i);                   //数字i就是玩家的命令。
                }
                else
                {
                    cout << "Do not get lock." << endl;
                }
            }
        }
    
        bool outMsgProc(int& command)
        {
            //lock_guard<mutex> sbguard(my_mutex);
            my_mutex.lock();    //要先lock
            unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
    
            std::chrono::milliseconds dura(2000);          //休息2秒
            std::this_thread::sleep_for(dura);
    
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                return true;
            }
            else
            {
                return false;
            }
        }
    
        //把数据从消息队列中取出
        void outMsgRecvQueue()
        {
            int i;
            int command = 0;
            for (i = 0; i < 100000; ++i)
            {
                int result = outMsgProc(command);
                if (result == true)
                {
                    cout << "command = " << command << endl;
                }
                else
                {
                    cout << "msgQueue is empty" << endl;
                }
            }
        }
    
    private:
        list<int> msgQueue;
        mutex my_mutex;       //创建一个互斥量
    };
    
    int main()
    {
        A myobj;
        thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
        thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    
        myOutMsg.join();
        myInMsg.join();
    
        cout << "main thread end..." << endl;
        return 0;
    }
 //(3.4)release() 返回管理的mutex对象的指针,并释放所有权。unique_lock和mutex不再有关系。
    // 如果原来mutex处于加锁状态,那就需要自己去解锁。人们常把锁头锁住代码的多少称为粒度。
 #include<iostream>
    #include<thread>
    #include<vector>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class A
    {
    public:
        //把收到的消息,入到一个队列中
        void inMsgRecvQueue()
        {
            int i;
            for (i = 0; i < 100000; ++i)
            {
                cout << "push_back num = " << i << endl;
                //lock之后只能有一个线程可以对msgQueue队列做操作
                //lock_guard<mutex> sbguard(my_mutex);
                unique_lock<mutex> my_unique_lock(my_mutex);
                std::mutex* ptx = my_unique_lock.release();          //互斥量已经加锁,程序员有责任去解锁
    
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
                ptx->unlock();
    
            }
        }
    
        bool outMsgProc(int& command)
        {
            //lock_guard<mutex> sbguard(my_mutex);
            my_mutex.lock();    //要先lock
            unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
    
            std::chrono::milliseconds dura(2000);          //休息2秒
            std::this_thread::sleep_for(dura);
    
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                return true;
            }
            else
            {
                return false;
            }
        }
    
        //把数据从消息队列中取出
        void outMsgRecvQueue()
        {
            int i;
            int command = 0;
            for (i = 0; i < 100000; ++i)
            {
                int result = outMsgProc(command);
                if (result == true)
                {
                    cout << "command = " << command << endl;
                }
                else
                {
                    cout << "msgQueue is empty" << endl;
                }
            }
        }
    
    private:
        list<int> msgQueue;
        mutex my_mutex;       //创建一个互斥量
    };
    
    int main()
    {
        A myobj;
        thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
        thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    
        myOutMsg.join();
        myInMsg.join();
    
        cout << "main thread end..." << endl;
        return 0;
    }
//(4)unique_lock所有权的传递
//unique_lock的所有权是可以转移的,但是不能复制。unique也是可以返回的。
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
using namespace std;
class A
{
public:
    unique_lock<mutex> rtn_unique_lock()            //返回一个unique_lock
    {
        unique_lock<mutex> tmpguard(my_mutex);
        return tmpguard;           //从函数返回一个局部的unique_lock对象是可以的,返回局部对象tmpguard
                                   //会导致系统生成临时的unique_lock对象,并且调用移动构造函数。
    }
public:
    //把收到的消息,入到一个队列中
    void inMsgRecvQueue()
    {
        int i;
        for (i = 0; i < 100000; ++i)
        {
            cout << "push_back num = " << i << endl;
            //lock之后只能有一个线程可以对msgQueue队列做操作
            //lock_guard<mutex> sbguard(my_mutex);
            unique_lock<mutex> my_unique_lock(my_mutex);
            unique_lock<mutex> mu_unique_lock_t(std::move(my_unique_lock));    //移动语意,my_unique_lock就为空了
            msgQueue.push_back(i);                   //数字i就是玩家的命令
        }
    }
    bool outMsgProc(int& command)
    {
        //lock_guard<mutex> sbguard(my_mutex);
        my_mutex.lock();    //要先lock
        unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock);
        std::chrono::milliseconds dura(2000);          //休息2秒
        std::this_thread::sleep_for(dura);
        if (!msgQueue.empty())
        {
            //消息不为空
            command = msgQueue.front();
            msgQueue.pop_front();          //移除首元素
            return true;
        }
        else
        {
            return false;
        }
    }
    //把数据从消息队列中取出
    void outMsgRecvQueue()
    {
        int i;
        int command = 0;
        for (i = 0; i < 100000; ++i)
        {
            int result = outMsgProc(command);
            if (result == true)
            {
                cout << "command = " << command << endl;
            }
            else
            {
                cout << "msgQueue is empty" << endl;
            }
        }
    }
private:
    list<int> msgQueue;
    mutex my_mutex;       //创建一个互斥量
};
int main()
{
    A myobj;
    thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj));   //保证线程中用的同一个对象
    thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
    myOutMsg.join();
    myInMsg.join();
    cout << "main thread end..." << endl;
    return 0;
}
posted on 2021-10-13 08:27 xcxfury001 阅读(412) 评论(0) 收藏 举报
 
                    
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号