多线程数据共享

多线程数据共享时引发的问题:

  1. 有两个售票窗口,两个窗口同时查询了同一次列车的余票信息,然后同时锁定同一个座位并卖出,此时,同一个座位被出售了两次。
  2. 生产者/消费者

一、互斥量(mutex)

可以理解成一个锁,只有锁成功才会继续向下执行,否则阻塞线程。
使用原则:只保护需要保护的信息。

  1. lock(), unlock()必须成对出现
#include 
#include 
#include 
#include 

using namespace std;

class A {
public:
    void inMsgRecvQueue()
    {
        for (int i = 0; i < 10000; ++i) {
            cout << "push one command : " << i << endl;
            my_mutex.lock();
            msgRecvQueue.push_back(i);
            my_mutex.unlock();
        }
    }

    bool outMsgProc(int &command) {
        my_mutex.lock();
        if (!msgRecvQueue.empty()) {
            //消息不为空
            command = msgRecvQueue.front();
            //cout << "received command is " << command << endl;
            msgRecvQueue.pop_front();
            my_mutex.unlock();  //解锁
            return true;
        }
        my_mutex.unlock(); //解锁
        return false;
    }
    void outMsgRecvQueue()
    {
        for (int i = 0; i < 10000; ++i) {
            int command = 0;
            while (!outMsgProc(command)) {
                //消息队列为空
                cout << "msgRecvQueue is empty" << endl;
            }
            cout << "received command is " << command << endl;
        }
    }
private:
    list msgRecvQueue; //容器,收到的消息
    std::mutex my_mutex; //互斥量,lock()和unlock()必须成对使用
};

int main() {
    A myobj;
    std::thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
    std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);

    myInMsgObj.join();
    myOutMsgObj.join();

    return 0;
}
  1. std::lock_guard()类模板,取代lock()和unlock(),作用就是会主动析构,不再需要unlock()
    lock_guard构造函数里执行了lock(),lock_guard析构函数里执行了unlock(),所以当lock_guard对象生命周期结束,就会自行unlock()
#include 
#include 
#include 
#include 

using namespace std;

class A {
public:
    void inMsgRecvQueue()
    {
        for (int i = 0; i < 10000; ++i) {
            cout << "push one command : " << i << endl;
            //my_mutex.lock();
            //msgRecvQueue.push_back(i);
            //my_mutex.unlock();
            { //第二种写法
                //{}显式声明sbguard的生命周期,出了{}sbguard会被系统自动回收,不再需要lock()和unlock()
                std::lock_guard sbguard(my_mutex); 
                msgRecvQueue.push_back(i);
            }
            //do else...
        }
    }

    bool outMsgProc(int &command) {
        //my_mutex.lock();
        //if (!msgRecvQueue.empty()) {
        //  //消息不为空
        //  command = msgRecvQueue.front();
        //  //cout << "received command is " << command << endl;
        //  msgRecvQueue.pop_front();
        //  my_mutex.unlock();  //解锁
        //  return true;
        //}
        //my_mutex.unlock(); //解锁

        std::lock_guard sbguard(my_mutex); //lock_guard构造函数里执行了lock()
                                                       //lock_guard析构函数里执行了unlock()
        if (!msgRecvQueue.empty()) {
            //消息不为空
            command = msgRecvQueue.front();
            //cout << "received command is " << command << endl;
            msgRecvQueue.pop_front();
            return true;
        }
        return false;
    }
    void outMsgRecvQueue()
    {
        for (int i = 0; i < 10000; ++i) {
            int command = 0;
            while (!outMsgProc(command)) {
                //消息队列为空
                cout << "msgRecvQueue is empty" << endl;
            }
            cout << "received command is " << command << endl;
        }
    }
private:
    list msgRecvQueue; //容器,收到的消息
    std::mutex my_mutex; //互斥量,lock()和unlock()必须成对使用
};

int main() {
    A myobj;
    std::thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
    std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);

    myInMsgObj.join();
    myOutMsgObj.join();

    return 0;
}

你可能感兴趣的:(多线程数据共享)