多线程数据共享

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

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

一、互斥量(mutex)

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

  1. lock(), unlock()必须成对出现
#include <iostream>
#include <thread>
#include <list>
#include <mutex>

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<int> 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 <iostream>
#include <thread>
#include <list>
#include <mutex>

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<std::mutex> 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<std::mutex> 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<int> 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;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容