创建多个线程、数据共享问题

  • Post author:
  • Post category:其他

一.创建和等待多个线程

  • 多个线程执行的顺序是乱的,与操作系统内部对线程的调度机制有关。
  • 主线程会等待所有的线程运行结束,最后主线程结束。
  • 把thread对象放入容器里面管理,这对一次创建大量的线程并对线程进行管理很方便。
#include <bits/stdc++.h>
#include <thread>
using namespace std;

void myPrint(int num){
    cout<<"线程编号:"<<num<<endl;
    cout<<"线程结束,编号是:"<<num<<endl;
    return;
}
int main(){
    vector<thread> myThreads;
    for(int i = 0; i < 10; i++){
        myThreads.push_back(thread(myPrint,i)); //创建并开始执行线程
    }
    for(auto it = myThreads.begin(); it != myThreads.end(); it++){
        it->join(); //等待10个线程都返回
    }
    cout<<"I love China!"<<endl;
    return 0;
}  

二.数据共享问题分析

1.只读的数据

是安全稳定的,不需要特别的处理手段;直接读就可以。

2.有读有写

读者写者问题。需要进行特殊的处理。因为写一个数据需要好几个步骤,有可能在写的过程中操作系统把当前时间片调度给了其他线程,就会导致程序出现不可预知的问题。

三.共享数据的保护案例代码

网络游戏服务器,有两个自己创建的线程,一个线程收集玩家命令(用数字代表玩家发的命令),并把命令写到一个队列中;另外一个线程从队列中取出玩家发送过来的命令,执行玩家的动作。

#include <bits/stdc++.h>
#include <thread>
using namespace std;

//成员函数作为线程的入口函数
class A{
    public:
    //把收到的玩家命令放到队列的一个线程    写
    void inMsgRecvQueue(){
        for(int i = 0; i < 100000; i++){ //模拟了100000次
            cout<<"inMsgRecvQueue执行,插入一个元素:"<<i<<endl;
            msgRecvQueue.push_back(i);
        }
    }
    //处理玩家命令的线程   读
    void outMsgRecvQueue(){
        for(int i = 0; i < 100000; i++){ //模拟了100000次
            if(!msgRecvQueue.empty()){ //消息队列不为空
                int command = msgRecvQueue.front();
                msgRecvQueue.pop_front();
                //处理数据
              
            }else{
                cout<<"outMsgRecvQueue执行,消息队列为空"<<i<<endl;
            }
        }
        cout<<"end"<<endl;
    }
    private:
    list<int> msgRecvQueue; //玩家发送的命令
};
int main(){
    A obj;
    thread myOut(&A::outMsgRecvQueue,ref(obj));//第二个参数是引用,才能保证线程里用的是同一个对象
    thread myIn(&A::inMsgRecvQueue,ref(obj));//第二个参数是引用,才能保证线程里用的是同一个对象

    myIn.join();
    myOut.join();
    return 0;
}  

这个代码执行会出问题。
读线程和写线程同时开始运行,当写的时候,执行到msgRecvQueue.push_back(i)的时候,因为这个操作不是原子操作,运行到一半的时候,调度到读线程,执行msgRecvQueue.pop_front(),因为不是原子操作,当运行到一半的时候,又调度了到其他线程。这就会出现异常,程序不稳定。


版权声明:本文为jinjia649472189原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。