C++多线程编程第五讲--互斥量概念、用法、死锁演示及解决详解
//(1)互斥量的(mutex)的基本概念
// 就是一个类的对象。多个线程可以尝试对一个mutex的对象进行lock,但是只有一个线程成功,其他线程需要等待。
//(2)互斥量的用法
    //(2.1)lock(), 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队列做操作
                my_mutex.lock();
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
                my_mutex.unlock();
            }
        }
    
        bool outMsgProc(int& command)
        {
            my_mutex.lock();
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                my_mutex.unlock();
                return true;
            }
            else
            {
                my_mutex.unlock();
                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::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);
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
            }
        }
    
        bool outMsgProc(int& command)
        {
            lock_guard<mutex> sbguard(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;
    }
//(3)死锁:必须要有两把锁,才能出现死锁。
    //(3.1)死锁演示
  #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队列做操作
                my_mutex1.lock();
                //...
                my_mutex2.lock();
                //...
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
                //...
                my_mutex2.unlock();
                //...
                my_mutex1.unlock();
    
            }
        }
    
        bool outMsgProc(int& command)
        {
            my_mutex2.lock();
            //...
            my_mutex1.lock();
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                my_mutex1.unlock();
                my_mutex2.unlock();
                return true;
            }
            else
            {
                my_mutex1.unlock();
                my_mutex2.unlock();
                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_mutex1;
        mutex my_mutex2;
    };
    
    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.2)死锁的一般解决方案:只要保证锁的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队列做操作
                my_mutex1.lock();
                //...
                my_mutex2.lock();
                //...
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
                //...
                my_mutex2.unlock();
                //...
                my_mutex1.unlock();
    
            }
        }
    
        bool outMsgProc(int& command)
        {
            my_mutex1.lock();
            //...
            my_mutex2.lock();
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                my_mutex2.unlock();
                my_mutex1.unlock();
                return true;
            }
            else
            {
                my_mutex2.unlock();
                my_mutex1.unlock();
                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_mutex1;
        mutex my_mutex2;
    };
    
    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.3)std::lock()函数模板
    // 一次锁住两个或两个以上的互斥量。如果这些锁中其中有一个没有lock成功,则释放已经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队列做操作
                std::lock(my_mutex1, my_mutex2);
                //...
                msgQueue.push_back(i);                   //数字i就是玩家的命令。
                //...
                my_mutex2.unlock();
                //...
                my_mutex1.unlock();
    
            }
        }
    
        bool outMsgProc(int& command)
        {
            std::lock(my_mutex1, my_mutex2);
            if (!msgQueue.empty())
            {
                //消息不为空
                command = msgQueue.front();
                msgQueue.pop_front();          //移除首元素
    
                my_mutex2.unlock();
                my_mutex1.unlock();
                return true;
            }
            else
            {
                my_mutex2.unlock();
                my_mutex1.unlock();
                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_mutex1;
        mutex my_mutex2;
    };
    
    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)std::lock_guard的adopt_lock参数
    //不必自己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队列做操作
            std::lock(my_mutex1, my_mutex2);
            lock_guard<mutex> lock_guard1(my_mutex1, std::adopt_lock);
            lock_guard<mutex> lock_guard2(my_mutex2, std::adopt_lock);
            //...
            msgQueue.push_back(i);                   //数字i就是玩家的命令。
            //...
        }
    }
    bool outMsgProc(int &command)
    {
        std::lock(my_mutex1, my_mutex2);
        lock_guard<mutex> lock_guard1(my_mutex1, std::adopt_lock);
        lock_guard<mutex> lock_guard2(my_mutex2, 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_mutex1;
    mutex my_mutex2;
};
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-07 18:31 xcxfury001 阅读(93) 评论(0) 收藏 举报
 
                    
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号