站长网 语言 C++多线程基本概念及其创建线程的操作

C++多线程基本概念及其创建线程的操作

副标题#e# 并发、进程、线程的基本概念 并发两个或者多个任务(独立的活动)同时发生(进行):一个程序通知执行多个独立的任务并发假象(不是真正的并发):单核CPU通过上下文切换方式实现进程 进程计算机中的程序关于某数据集合上的一次运行活动 进程特性 动态性

副标题#e#

并发、进程、线程的基本概念

并发两个或者多个任务(独立的活动)同时发生(进行):一个程序通知执行多个独立的任务并发假象(不是真正的并发):单核CPU通过上下文切换方式实现进程

进程计算机中的程序关于某数据集合上的一次运行活动

进程特性

动态性:进程是程序的一次执行过程,是临时的,有生命期,是动态产生,动态消亡的;

并发性:任何进程都可以同其他进行一起并发执行;

独立性:进程是系统进行资源分配和调度的一个独立单位;

结构性:进程由程序,数据和进程控制块三部分组成

线程每个进程都有一个主线程并且主线程是唯一的,也就是一个进程只能有一个主线程。vs编译器中ctr+f5编译运行程序时,实际是主线程调用mian函数中的代码。线程可以理解为代码执行通道,除了主线程之外,可以自己创建其他线程。

并发实现方案

主要解决是进程间通信问题

同一电脑上可通过管道,文件,消息队列,共享内存等方式实现

不同电脑可通过socket网络通信实现

多个进程实现并发

单独进程,多个线程实现并发 即一个主线程,多个子线程实现并发一个进程中的所有线程共享内存空间(共享内存),例如全局变量,指针引用等,所以多线程开销远远小于多进程。共享内存也会导致数据一致性问题(资源竞争问题)。

C++线程编程基本操作

1.首先需要包含thread头文件

#include <thread> 

#include <iostream> 

2.创建线程: thread类创建一个线程

#include <thread> 

void print() 

 std::cout<<"子线程"<<endl;     

int main() 

    //运行程序会调用abort函数终止程序     

    std::thread t1(print);    

    std::cout<<"主线程"<<std::endl; 

3.join:加入/汇合线程。阻塞主线程,等待子线程执行结束,可理解为依附功能

#include <thread> 

void print() 

 std::cout<<"子线程"<<endl;     

int main() 

    std::thread t1(print);    

    t1.join();      //阻塞主线程,等待子线程执行结束 

    std::cout<<"主线程"<<std::endl; 

    return 0; 

4.detach:分离,剥离依附关系,驻留后台

#include <thread> 

#include <iostream> 

#include <windows.h> 

void print()  

 for (int i = 0; i < 10; i++)  

 { 

  std::cout << "子线程"<<i << std::endl; 

 } 

int main()  

 std::thread t1(print); 

 std::cout << "主线程" << std::endl; 

    //可用Sleep延时实现结果演示 

 t1.detach(); 

 return 0; 

注意:一旦detach线程后,便不可再使用join线程。

5.joinable:判断当前线程是否可以join或deatch,如果可以返回true,不能返回false

#include <thread> 

#include <iostream> 

void print()  

 for (int i = 0; i < 10; i++)  

 { 

  std::cout << "子线程"<<i << std::endl; 

 } 

int main()  

 std::thread t1(print); 

 t1.detach(); 

 if (t1.joinable())  

 { 

  t1.join(); 

  std::cout << "可join" << std::endl; 

 } 

 std::cout << "主线程" << std::endl; 

 return 0; 

其他创建线程方法

1.用类和对象

#include <thread> 

#include <iostream> 

class Function  

public: 

 void operator()()  

  std::cout << "子线程" << std::endl; 

 } 

}; 

int main()  

 Function object; 

 std::thread t1(object);    //可调用对象即可 

 t1.join(); 

 std::thread t2((Function())); 

 t2.join(); 

 std::cout << "主线程" << std::endl; 

 return 0; 

2.Lambda表达式

#include <thread> 

#include <iostream> 

int main()  

 

 

 std::thread t1([] {std::cout << "子线程" << std::endl; }); 

 t1.join(); 

 std::cout << "主线程" << std::endl; 

 return 0; 

3.带引用参数创建方式

#include <thread> 

#include <iostream> 

#include <thread> 

void printInfo(int& num)  

 num = 1001; 

 std::cout << "子进程:"<<num << std::endl; 

int main()  

 int num = 0; 

 //std::ref 用于包装按引用传递的值。 

 //std::cref 用于包装按const引用传递的值 

 //error C2672: “invoke”: 未找到匹配的重载函数 

 std::thread t(printInfo, std::ref(num));     

 t.join(); 

 std::cout << "主线程:"<<num << std::endl; 

 return 0; 

4.带智能指针参数创建方式

#include <thread> 

#include <iostream> 

#include <thread> 

void printInfo(std::unique_ptr<int> ptr)  

 std::cout << "子线程:"<<ptr.get() << std::endl; 

int main()  

 std::unique_ptr<int> ptr(new int(100)); 

 std::cout << "主线程:" << ptr.get() << std::endl;   

 std::thread t(printInfo,std::move(ptr));     

 t.join(); 

#p#副标题#e#

 std::cout << "主线程:"<<ptr.get() << std::endl;  //主线程:00000000 move掉了 

 return 0; 

5.类的成员函数

#include <thread> 

#include <iostream> 

#include <thread> 

class MM  

public: 

 void print(int& num)  

  num = 1001; 

  std::cout << "子线程:"<<num << std::endl; 

 } 

}; 

int main()  

 MM mm; 

 int num = 10; 

 std::thread t(&MM::print,mm,std::ref(num));     

 t.join(); 

 std::cout << "主线程:"<< num << std::endl; 

 return 0; 

好了,创建线程就介绍到这里,大家可以先练习一下,下章节讲解共享数据访问。

本文来自网络,不代表站长网立场,转载请注明出处:https://www.zwzz.com.cn/html/biancheng/yuyan/2021/0523/4680.html

作者: dawei

【声明】:站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。
联系我们

联系我们

0577-28828765

在线咨询: QQ交谈

邮箱: xwei067@foxmail.com

工作时间:周一至周五,9:00-17:30,节假日休息

返回顶部