首页 文章详情

C++多线程编程(二)

C语言编程基础 | 279 2021-03-03 14:25 0 0 0
UniSMS (合一短信)

多线程是程序员必须掌握的一门技术,本文主要是针对于C++新标准中多线程库,需要具备一定C++基础方可学习。

前言


本章节是C++多线程编程第二课,C++不熟悉的可以转接C++专辑教程,本章节主要讲解C++多线程编程中容器创建线程以及数据共享问题。

容器创建管理线程


#include <vector>#include <iostream>#include <thread>void printTest(int num) {  std::cout << "子线程:" << num << "启动" << std::endl;  std::cout << "子线程:" << num << "结束" << std::endl;}int main() {  std::vector<std::thread* > test;  for (int i = 0; i < 10; i++)   {    test.push_back(new std::thread(printTest, i));  }  for (auto& pmove : test)  {    pmove->join();  }  std::cout << "主线程" << std::endl;  return 0;}
C++数据共享问题分析


1.只读数据:稳定安全,不需要特殊处理,直接读即可

#include <vector>#include <iostream>#include <thread>std::vector<int> g_data={ 1,2,3 };void printTest(int num) {  std::cout << "子线程:" << num << "读操作" << std::endl;  for (auto pmove : g_data)   {    std::cout << pmove << std::endl;  }}int main() {  std::vector<std::thread* > test;  for (int i = 0; i < 10; i++)   {    test.push_back(new std::thread(printTest, i));  }  for (auto& pmove : test)  {    pmove->join();  }  std::cout << "主线程" << std::endl;  return 0;}

2.有读有写:需要做特别处理(写只做写,读只做读操作,保持共享数据只有唯一操作),不然会引发奔溃

#include <list>#include <iostream>#include <thread>class SeaKing {public:  void makeFriend(){    for (int i = 0; i < 100000; i++)     {      std::cout << "增加一个" << std::endl;      mm.push_back(i);    }  }  void breakUp() {    for (int i = 0; i < 100000; i++)     {      if (!mm.empty())       {        std::cout << "减少一个:"<<mm.front() << std::endl;        mm.pop_front();      }      else       {        std::cout << "已空" << std::endl;      }    }  }protected:  std::list<int> mm;};int main() {  SeaKing man;  std::thread t1(&SeaKing::makeFriend, &man);  std::thread t2(&SeaKing::breakUp, &man);  t1.join();  t2.join();  return 0;}//以上程序会异常退
加锁的方式解决数据共享问题


1.互斥量mutex: 互斥量可以理解为锁,他是一个mutex类的对象

  • 通过调用成员函数lock函数进行加锁

  • 通过调用成员函数unlock函数进行解锁

#include <list>#include <iostream>#include <thread>#include <mutex>        //1.包含头文件class SeaKing {public:  void makeFriend(){    for (int i = 0; i < 100000; i++)     {      m_mutex.lock();      std::cout << "增加一个" << std::endl;      mm.push_back(i);      m_mutex.unlock();    }  }  bool readInfo() {    m_mutex.lock();        //2.加锁    if (!mm.empty())    {      std::cout << "减少一个:" << mm.front() << std::endl;      mm.pop_front();      m_mutex.unlock();      return true;    }    m_mutex.unlock();    return false;  }  void breakUp() {    for (int i = 0; i < 100000; i++)    {      int result = readInfo();      if (result == false)       {        std::cout << "已空" << std::endl;      }    }  }protected:  std::list<int> mm;  std::mutex m_mutex;        //创建互斥量对象};int main() {  SeaKing man;  std::thread t1(&SeaKing::makeFriend, &man);  std::thread t2(&SeaKing::breakUp, &man);  t1.join();  t2.join();  return 0;}

注意:lock函数与unlock都是成对出现,如果lock了没有调用unlock会引发异常,abort终止程序

2.通过lock_guard加锁。

#include <list>#include <iostream>#include <thread>#include <mutex>class SeaKing {public:  void makeFriend(){    std::lock_guard<std::mutex> sbguard(m_mutex);    for (int i = 0; i < 100000; i++)     {      std::cout << "增加一个" << std::endl;      mm.push_back(i);    }  }  bool readInfo() {    std::lock_guard<std::mutex> sbguard(m_mutex);    if (!mm.empty())    {      std::cout << "减少一个:" << mm.front() << std::endl;      mm.pop_front();      return true;    }    return false;  }  void breakUp() {    for (int i = 0; i < 100000; i++)    {      int result = readInfo();      if (result == false)       {        std::cout << "已空" << std::endl;      }    }  }protected:  std::list<int> mm;  std::mutex m_mutex;};int main() {  SeaKing man;  std::thread t1(&SeaKing::makeFriend, &man);  std::thread t2(&SeaKing::breakUp, &man);  t1.join();  t2.join();  return 0;}

其实lock_guard 在构造函数中进行lock,在析构函数中进行unlock,本质上还是lock与unlock操作。

好了,创建线程就介绍到这里,大家可以先练习一下,下章节讲解共享数据访问。喜欢的不如点个“在看”吧



good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter