栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C++】多线程thread

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++】多线程thread

进程和线程这部分呢我之前在我Linux中写过这些东西,和C++中线程的概念差不多,大家可以去看一下:

Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地址空间,线程共享进程中的地址空间进程的创建消耗资源大,线程的创建相对较小进程的切换开销大,线程的切换开销相对较小进程:程序执行的过程叫进程。线程:进程内部的一条执行序列或执行路径,一个进程可以包含多条线程(多线程)!每个进程最少有一个线程,例如下面代码:#include int main(){ return 0;} ...https://blog.csdn.net/qq_45829112/article/details/121458560

进程和线程的区别:

进程是资源分配的最小单位,线程是CPU调度的最小单位

进程有自己的独立地址空间,线程共享进程中的地址空间

进程的创建消耗资源大,线程的创建相对较小

进程的切换开销大,线程的切换开销相对较小

进程:程序执行的过程叫进程。

线程:进程内部的一条执行序列或执行路径,一个进程可以包含多条线程(多线程)!

每个进程最少有一个线程,例如下面代码:

#include 
using namespace std;
 
int main()
{
    return 0;
}

虽然只有一个主函数main,主函数的线程又叫主线程,其他的线程都叫它的子线程。

上面看完之后大致明白了线程的进程的区别,下面我们来看一下常用到的函数有哪些:

 上图来自于C++帮助文档:

std::thread - cppreference.comhttps://zh.cppreference.com/w/cpp/thread/thread

先来看第一个构造函数:

打开它的构造函数,我们可以看到:

上图我们可以看到我们在下面这行代码后有个delete,也就是拷贝构造函数被删除了,不可以通过拷贝构造来创建线程!

thread(  const thread& ) = delete;

        我们只能通过缺省构造,移动构造,函数构建和类对象来构建对象!!!

缺省构建:
#include
using namespqce std;

int main()
{
    std::thread t1;
    return 0;
}

值得一提的是,上述t1根本意义上不算是一个线程,原因是构造不表示线程的新 thread 对象, 只是一个空的thread对象,因为没有指定函数指针,所以不会启动一个线程。

移动构造/函数构建:
void f1(int& n)
{
	n += 10;
}

int main()
{
	int n = 0;
	std::thread t3(f1, std::ref(n)); //std::ref()将值按引用传递
    //因为上述函数f1中接收的参数是按照引用来接受的,所以传值引用
	std::thread t4(std::move(t3)); //std::,ove()将值按照右值传递
    //在t4创建时,t3就已经不是一个线程了  将t3的资源转移给t4
}
 类对象构建对象:
class foo
{
public:
	void fun()
	{
		cout << "foo::fun run" << endl;
	}
};

int main()
{
	foo f;
	thread t5(&foo::fun, &f);
	t5.join();
	return 0;
}
joinable函数 先来看下官方的解释: 这玩意主要作用就是检测线程是否为一个可执行线程,可执行返回true,否则返回false  我们来看下这个函数需要注意的点:

 下面代码来演示:

void foo()
{
	std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
	thread t;   //缺省构造的线程
	std::cout << t.joinable() << endl;

	t = thread(foo); 
	cout << t.joinable() << endl;
	t.join();

	thread t1(std::move(t));   
	cout << t1.joinable() << endl;

	std::cout << t.joinable() << endl;//移动之后的的tjoinable为false
}

我们可以看到,t为缺省构造的线程,t1为移动构造的线程,看下面运行结果:

 我们可以看到结果符合我们上图所说到的joinable()函数特点!!!

get_id()函数

我们先来看官方的解释以及返回值!

 下面来看代码演示:

int main()
{
	thread t1(fun,std::ref(g_max));
	std::thread::id t1_id = t1.get_id();
	cout << t1_id << endl;

	t1.join();
	return 0;
}

运行结果:

join()函数 

 join()函数的作用就是起到一个阻塞作用直到需要等待的线程返回,才会继续执行下面的代码。

直接来看代码演示:

void foo()
{
	cout << "foo run" << endl;
	std::this_thread::sleep_for(std::chrono::seconds(10)); //在该线程中阻塞一秒
}

void bar()
{
	cout << "bar run" << endl;
	std::this_thread::sleep_for(std::chrono::seconds(10)); //在该线程中阻塞一秒
}

int main()
{
	std::thread th1(foo);
	std::thread th2(bar);

	std::cout << "waiting for helpers to finish..." << std::endl;
    th1.join();
    th2.join();
	std::cout << "done!n";
}

在两线程中分别都停留10s然后才退出,运行起来就会发现程序会阻塞十秒然后才会退出到主界面,说白了join()函数就是等待线程的结束才会继续执行,否则就一直阻塞在join()函数这块!!!

detach()函数

void fun()
{
	std::this_thread::sleep_for(std::chrono::seconds(100));
	cout << "AAAA" << endl;
}

int main()
{
	thread th1(fun);
	th1.detach();

	cout << "BBBB" << endl;
	return 0;
}

上述代码我们可以看出应该是主线程运行之后,进入到子线程th1,然后在fun函数中阻塞100s,但是由于使用了detach()函数,使得主线程与子线程th1分离了,没关系了,但是随着主线程main的退出,子线程th1也将被退出!!!

join()和detach()函数之后,对线程再次进行joinable将会是false!!!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/767335.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号