• C++多线程基础学习笔记(四)


    一、创建多个子线程

    前面三章讲的例子都是只有一个子线程和主线程,然而实际中有多个子线程。那么下面介绍如何创建多个子线程。

     1 #include <iostream>
     2 #include <vector>
     3 #include <list>
     4 #include <thread>
     5 using namespace std;
     6 
     7 void mythread(int i)
     8 {
     9     cout << "id为" << std::this_thread::get_id() << "的线程" << endl;
    10     cout << "i=" << i << endl;
    11     return;
    12 }
    13 
    14 int main()
    15 {
    16     vector<thread> mythreads;
    17     for (int i = 0; i < 10; i++)
    18     {
    19         mythreads.push_back(thread(mythread, i));  //创建是10个线程并放入容器中
    20     }
    21     for (auto ite = mythreads.begin(); ite != mythreads.end(); ++ite)
    22     {
    23         ite->join();      //主线程等待10个线程执行完
    24     }
    25     cout << "主线程执行完毕" << endl;
    26     system("pause");
    27     return 0;
    28 }

    运行结果

    可以看出,虽然所有子线程执行完了才到主线程,但各个子线程的执行期间是乱的,没有谁等谁。那么就会引发一个数据共享的问题。

    二、数据共享问题

    如果多个线程之间知识单纯的读取数据,那么程序是不会出现奔溃等严重问题的,是安全稳定的。但如果既读数据又写数据,程序很有可能崩溃。比如有5个线程,2个线程写数据,3个线程读取同样的数据,试想如果写数据的线程还没写入数据,其他线程就进行读数据操作了,那么必然会出现问题。下面举一个例子说明。

     1 #include <iostream>
     2 #include <vector>
     3 #include <list>
     4 #include <thread>
     5 using namespace std;
     6 //队列,先进先出
     7 class A 
     8 {
     9 private:
    10     list<int> msg;
    11 public:
    12     //把数据写入队列
    13     void inMsgRecv()
    14     {
    15         for (int i = 0; i < 10000; i++)
    16         {
    17             cout << "插入一个元素" << i << endl;
    18             msg.push_back(i);
    19         }
    20     }
    21     //从队列读数据
    22     void outMsgRecv()
    23     {
    24         for (int i = 0; i < 10000; i++)
    25         {
    26             if (!msg.empty())
    27             {
    28                 int GetMsg = msg.front();   //接受消息队列的首部
    29                 msg.pop_front();            //移除首部
    30                 //....然后可以对GetMsg进行你想要的操作
    31                 //cout << "GetMsg:" << GetMsg << endl;
    32             }
    33             else
    34             {
    35                 cout << "没有数据可读" << endl;
    36             }
    37         }
    38     }
    39 };
    40 
    41 int main()
    42 {
    43     A myobj;
    44     //以成员函数作为线程函数,第一个&是取地址,第二个&是引用
    45     thread mythread1(&A::inMsgRecv, &myobj);
    46     thread mythread2(&A::outMsgRecv, &myobj);
    47     mythread1.join();
    48     mythread2.join();
    49     system("pause");
    50     return 0;
    51 }

    运行结果

    那么要处理多线程的数据共享问题,就要涉及一个概念“互斥量”,下面一章将会讲到。

  • 相关阅读:
    DataGridView在vb.net中的操作技巧
    0、(空字串)、Null、Empty、与Nothing的区别
    System.Timers.Timer与System.Windows.Forms.Timer 区别
    C#判断常见类型格式是否正确的类
    C#对系统注册表操作的类
    Socket基础知识分享
    怎样才能充分利用SQL索引
    通过建立Socket连接来快速判断数据库连接是否正确
    C#中各种数据类型转换的方法的类
    VB.Net C#代码转换工具
  • 原文地址:https://www.cnblogs.com/main404/p/11191892.html
Copyright © 2020-2023  润新知