如何创建多线程

本文详细介绍了C++中线程的创建与管理,包括使用`std::thread`创建线程,通过`join()`和`detach()`控制线程执行,以及`joinable()`的使用。示例代码展示了如何使用函数、类成员函数和lambda表达式启动线程,并讨论了`detach()`可能导致的不可控性。此外,还探讨了线程对象在`detach()`后生命周期的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

范例演示线程运行与开始

程序运行起来,生成一个进程,该程序所属的主线程开始运行。以下函数就是一个进程。

#include "pch.h"
#include <iostream>

int main()
{
    std::cout << "Hello World!\n"; 
	return 0;
}
  1. 主线程从main()函数开始执行,我们自己创建的线程,也需要从一个函数开始运行(初函数),一旦这个函数运行完毕 ,就代表我们的线程执行完毕。
  2. 整个进程是否执行完毕的标志是 :主线程是否执行完毕,若果是就代表整个进程执行完毕。此时,一般情况下,若果其他子线程还没有执行完毕,那么这些子线程也会被操作系统强行终止。所以,一般情况下,如果想保持子线程(自己创建的线程)的运行状态的话,一定要保持主线程运行,不要其运行完毕(有例外,以后解释见detach())。

如何写自己的线程:

thread

thread标准库里的类,myprint可调用对象,创建子线程,线程执行起点,线程开始执行。

join()

加入/汇合,术语阻塞,阻塞主线程,让主线程等待子线程执行完毕,然后子线程与主线程汇合,join执行完毕,主线程继续执行

  1. 包含一个头文件t#include < thread >;
  2. 初始函数;
  3. main()中写代码;如下:
#include "pch.h"
#include <iostream>
#include<thread>
void myprint()
{
	std::cout << "子线程开始执行。" << std::endl;
	//....
	//....
	std::cout << "子线程执行完毕。" << std::endl;
}
int main()
{
	std::thread mytobj(myprint);//thread标准库里的类,myprint可调用对象,创建子线程,线程执行起点,线程开始执行。
	mytobj.join();              //join()加入/汇合,术语阻塞,阻塞主线程,让主线程等待子线程执行完毕,然后子线程与主线程汇合,join执行完毕,主线程继续执行
	std::cout << "主线程安全退出!" << std::endl;
	return 0;
}

注意,此程序包含两个线程,即同事做两个任务,一个任务被阻止,另一个可以继续执行。join很重要,没有join程序报错,程序执行混乱;不能保证子线程在主线程之前结束。

detach()

a.传统多线程程序要等子线程执行完毕,然后自己在退出;detach():分离也就是主线程与子线程不汇合,各执行各的,不必等待;
b.为什么引入:我们创建很多子线程,让主线程逐个等待子线程结束,这种编程不太好,所以引入detach()一旦detach()后,与主线程关联的thread对象就会失去关联,子线程驻留在后台运行,被c++运行时库接管-建议少用


#include "pch.h"
#include <iostream>
#include<thread>
void myprint()
{
	std::cout << "子线程开始执行。" << std::endl;
	//  ...
	//....
	std::cout << "子线程执行完毕1。" << std::endl;
	std::cout << "子线程执行完毕2。" << std::endl;
	std::cout << "子线程执行完毕3。" << std::endl;
	std::cout << "子线程执行完毕4。" << std::endl;
	std::cout << "子线程执行完毕5。" << std::endl;
	std::cout << "子线程执行完毕6。" << std::endl;
	std::cout << "子线程执行完毕7。" << std::endl;
	std::cout << "子线程执行完毕8。" << std::endl;
	std::cout << "子线程执行完毕9。" << std::endl;
	std::cout << "子线程执行完毕10。" << std::endl;
}
int main()
{
	std::thread mytobj(myprint);
	mytobj.detach();
	std::cout << "主线程执行完毕。" << std::endl;
	return 0;
}

在这里插入图片描述
在这里插入图片描述
两次运行结果不一致,detach()会导致子线程失去控制,建议少用。一旦detach()后,不能join(),程序会报错。

joinable()

判断是否成功使用join()或detach(),成功返回false,否则返回else。


#include "pch.h"
#include <iostream>
#include<thread>
void myprint()
{
	std::cout << "子线程开始执行。" << std::endl;
	//  ...
	//....
	std::cout << "子线程执行完毕1。" << std::endl;
	std::cout << "子线程执行完毕2。" << std::endl;
	std::cout << "子线程执行完毕3。" << std::endl;
	std::cout << "子线程执行完毕4。" << std::endl;
	std::cout << "子线程执行完毕5。" << std::endl;
	std::cout << "子线程执行完毕6。" << std::endl;
	std::cout << "子线程执行完毕7。" << std::endl;
	std::cout << "子线程执行完毕8。" << std::endl;
	std::cout << "子线程执行完毕9。" << std::endl;
	std::cout << "子线程执行完毕10。" << std::endl;
}
int main()
{
	std::thread mytobj(myprint);
	if (mytobj.joinable())
	{
		std::cout << "joinable()==true" << std::endl;
	}
	else
	{
		std::cout << "joinable()==false" << std::endl;
	}
	mytobj.detach();
	if (mytobj.joinable())
	{
		std::cout << "joinable()==true" << std::endl;
	}
	else
	{
		std::cout << "joinable()==false" << std::endl;
	}
	std::cout << "主线程执行完毕。" << std::endl;
	return 0;
}

在这里插入图片描述

其他创建线程的方法

用类以及一个问题范例


#include "pch.h"
#include <iostream>
#include <thread>
class TA
{
public:
	void operator()() //
	{
		std::cout << "子线程开始执行。" << std::endl;
		//....
		std::cout << "子线程执行完毕。" << std::endl;
	}
};
int main()
{
	TA ta;
	std::thread mytobj2(ta);
	mytobj2.join();
	std::cout << "主线程执行完毕。" << std::endl;
	return 0;
}

在这里插入图片描述
疑问:一旦调用detach(),那主线程就结束了,这里用的ta对象还存在吗?
答:对象不存在,但是被复制到线程中去,执行完主线程后,ta被销毁,但所复制的对象依旧存在。所以,只要这个TA类对象里没有引用,没有指针,就不会产生问题。

用lambda表达式


#include "pch.h"
#include <iostream>
#include <thread>
int main()
{/*
	TA ta;
	std::thread mytobj2(ta);
	mytobj2.join();*/
	auto mylamthread = [] {
		std::cout << "我的线程开始执行。" << std::endl;
		//...
		std::cout << "我的线程执行完毕。" << std::endl;
	};
	std::thread mytobj4(mylamthread);
	mytobj4.join();
	std::cout << "主线程执行完毕。" << std::endl;
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值