并发与多线程四:创建多个线程,数据共享问题分析、案例代码

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include<list>

using namespace std;
vector<int> g_v = { 1,2,3 };//共享数据,只读
//线程入口函数
//void myprint(int inum)
//{
//    //cout << "myprint线程开始执行了,线程编号=" << inum << endl;
//    //cout<< "myprint线程结束执行了,线程编号=" << inum << endl;
//    cout << "id 为" << std::this_thread::get_id << "的线程打印g_v的值" << g_v[0] << g_v[1] << g_v[2] << endl;
//    return;
//}

class A
{
public:
    //把受到的消息(玩家命令)入到一个队列的线程
    void inmsgrectqueue()
    {
        for(int i=0;i<100;++i)
        {
            cout << "inmsgrectqueue()执行,插入一个元素" << i << endl;
            msgrectqueue.push_back(i);//假设这个数字i就是收到的命令,直接弄到消息队列中去。
        }
    }

    //把数据从消息队列中取出的线程
    void outmsgrectqueue()
    {
        for(int i=0;i<100;++i)
        {
            if(!msgrectqueue.empty())
            {
                //消息不为空
                int command = msgrectqueue.front();//返回第一个元素,但不检查元素是否存在
                msgrectqueue.pop_back();//移除第一个元素,但不返回;
                //这里就考虑处理数据...
            }
            else
            {
                //消息队列为空
                cout << "outmsgrectqueue()执行,但目前消息队列中为空" << i << endl;
            }
            cout << "end" << endl;
        }
    }

private:
    std::list<int> msgrectqueue;// 容器,专门用于代表玩家给咱们发送过来的命令
};
int main()
{
    ////一:创建和等待多个线程
    //vector<thread> mythreads;
    //////创建10个线程,线程入口函数统一使用myprint
    //////a)多个线程执行顺序是乱的,跟系统内部对线程的运行调度机制有关。
    //////b)主线程等待所有子线程运行结束,最后主线程结束,推荐使用join。
    //////c)把thread对象放到容器中管理,看起来像个thread对象数组,这对我们一次创建大量的线程并对大量线程进行管理比较方便
    //for(int i=0;i<10;i++)
    //{
    //    mythreads.push_back(thread(myprint, i));//创建10个线程,同时这10个线程已经开始执行。
    //}
    //for(auto iter=mythreads.begin();iter!=mythreads.end();++iter)
    //{
    //    iter->join();//等待10个线程都返回
    //}
    //cout << "i love china" << endl;


    //二。数据共享问题分析
    //(2.1)只读的数据,是安全稳定的,不需要特别的什么处理手段。直接读就可以。
    //(2.2)有读有写:2个线程写,8个线程读,如果代码没有特别的处理,那程序肯定崩溃。
    //最简单的不崩溃处理方法,读的时候不能写,写的时候不能读,2个线程不能同时写,8个线程不能同时读。

    //(2.3)其他案例
    //数据共享
    //北京--深圳 火车 t123 ,10个售票窗口 卖票,  1,2窗口  同时都要订99座

    //三。数据共享的保护案例代码
    //网络游戏服务器,两个自己创建的线程,一个线程收集玩家命令(用一个数字代码玩家发送的命令),并把命令写到一个队列中。
    //另外一个线程从队列中取出玩家发送过来的命令,解析,额案后执行玩家需要的动作。
    //vector,list ,list跟vector。list:频发的 按顺序插入和删除数据时效率高。vector容器随机的插入和删除数据效率高。
    

    //用成员函数为线程函数的方法来写线程;
    //代码化解决问题:引入一个C++解决多线程保护共享数据问题的第一个概念“互斥量”
    A myobja;
    std::thread myoutmsgobj(&A::outmsgrectqueue, &myobja);//第二个参数是(引用,才能保证线程里用的是同一个对象
    std::thread myinmsgobj(&A::inmsgrectqueue, &myobja);
    myoutmsgobj.join();
    myinmsgobj.join();
    return 0;
}

 

posted @ 2020-09-28 16:24  AI_ON  阅读(103)  评论(0)    收藏  举报