一个用于多线程共享数据保护测试的简易游戏服务器代码

发布时间 2023-11-25 14:11:53作者: Ann-
#include <iostream>
#include <thread>
#include <list>
#include <mutex>

//一个线程负责从客户端读取用户的命令,放入一个队列中;
//另一个线程负责从队列中读取命令并解析,假设用一个int变量代表一个命令。
class A
{
public:    
    //这里无法模拟从网络接受命令的过程,我们简单地用一个循环模拟。
    void inMsgRecvQueue();

    //这个函数把代码中涉及到共享数据访问的操作封装起来,方便加锁操作
    bool outMsgLULProc(int& command);
    void outMsgRecvQueue();


public:
    std::list<int> msgRecvQueue;
    std::mutex mutex_msgRecvQueue;
};

void A::inMsgRecvQueue()
{
    for (int i = 0; i < 10000; ++i)
    {
        msgRecvQueue.push_back(i);
        std::cout << "inMsgRecvQueue执行,插入一个元素" << i << " " << std::endl;
    }
    std::cout << "end of inRecvQueue " << std::endl;
}

bool A::outMsgLULProc(int& command)
{
    if (!msgRecvQueue.empty())
    {
        command = msgRecvQueue.front();
        msgRecvQueue.pop_front();
        return true;
    }
    return false;
}

void A::outMsgRecvQueue()
{
    int command = 0;
    for( int i=0; i<10000; i++ )
    {
        bool result = outMsgLULProc(command);
        if (result == true)
        {
            std::cout << "outMsgRecvQueue执行,读出一个元素" << command << " " << std::endl;
            //处理数据
        }
        else
        {
           //std::cout << "outMsgRecvQueue执行,但队列为空。" << std::endl;
        }
    }
    std::cout << "end of outMsgRecvQueue " << std::endl;
}

int main()
{
    std::cout << "begin of main " << std::endl;
    
    A myobja;
    //注意这里直接使用A::访问A的成员函数,并通过取地址得到函数指针; 这里使用&myobja有点歧义,它
    //不是取myobja的地址的意思,它的意思是使用myobja的引用。
    //这里使用引用才能保证两个线程里用的是用一个myobja对象。
    std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
    std::thread myOutnMsgObj(&A::outMsgRecvQueue, &myobja);

    myInMsgObj.join();
    myOutnMsgObj.join();

    std::cout << "end of main" << std::endl;
    return 0;
}