0
点赞
收藏
分享

微信扫一扫

多线程的数据共享保护案例


前言

假设有一个网络游戏服务器,创建了两个线程:

  1. 一个线程收集玩家命令(数字表示),并把命令数据写到队列中;
  2. 取出队列中玩家发送的命令并进行解析,最后执行玩家需要的动作。

mutex互斥量:使用lock()和unlock()

// 用成员函数作为线程函数
class A {
public:
// 入队操作
void inmsgRecvQueue() {
for (int i = 0; i < 100000; ++i) {
cout << "inmsgRecvQueue()函数执行,插入一个元素" << i << endl;
m_mutex.lock();
msgRecvQueue.push_back(i);
m_mutex.unlock();
}
}

bool isoutMsgRecvQueue(int& command) {
m_mutex.lock();
if (!msgRecvQueue.empty()) {
command = msgRecvQueue.front();
msgRecvQueue.pop_front();
m_mutex.unlock(); // 不能漏掉
return true;
}
m_mutex.unlock();
return false;
}
// 出队操作
void outmsgRecvQueue() {
for (int i = 0; i < 100000; ++i) {
int command = 0;
bool res = isoutMsgRecvQueue(command);
if (res) {
cout << "inmsgRecvQueue()函数执行,取出命令" << command << endl;
}
else {
cout << "inmsgRecvQueue()函数执行,但是目前队列为空" << i << endl;
}
}
cout << "end" << endl;
}

private:
std::list<int> msgRecvQueue; // 存储玩家发送的命令
std::mutex m_mutex;
};

int main()
{
A a;
std::thread outobj(&A::outmsgRecvQueue, &a); // 第二个参数用引用,保证用的是同一个a对象
std::thread inobj(&A::inmsgRecvQueue, &a);
outobj.join();
inobj.join();
return 0;
}

使用lock_guard类模板来替代lock()和unlock()

lock_guard类模板在函数或程序段结束是会在析构函数中调用unlock()来解锁,所以当任务很多的时候添加{ }是一种及时解锁的方法。

// 用成员函数作为线程函数
class A {
public:
// 入队操作
void inmsgRecvQueue() {
for (int i = 0; i < 100000; ++i) {
cout << "inmsgRecvQueue()函数执行,插入一个元素" << i << endl;
std::lock_guard<std::mutex> guard(m_mutex);
msgRecvQueue.push_back(i);
}
}

bool isoutMsgRecvQueue(int& command) {
std::lock_guard<std::mutex> guard(m_mutex);
if (!msgRecvQueue.empty()) {
command = msgRecvQueue.front();
msgRecvQueue.pop_front();
return true;
}
return false;
}
// 出队操作
void outmsgRecvQueue() {
for (int i = 0; i < 100000; ++i) {
int command = 0;
bool res = isoutMsgRecvQueue(command);
if (res) {
cout << "inmsgRecvQueue()函数执行,取出命令" << command << endl;
}
else {
cout << "inmsgRecvQueue()函数执行,但是目前队列为空" << i << endl;
}
}
cout << "end" << endl;
}

private:
std::list<int> msgRecvQueue; // 存储玩家发送的命令
std::mutex m_mutex;
};


举报

相关推荐

0 条评论