C++笔记之多线程编程3

本篇文章继续写线程中的join和detach。详细说明二者的区别!

一、线程状态:

在一个线程的生存期内,可以在多种状态之间切换,不同的操作系统可以实现不同的线程模型。定义许多不同的线程状态,每个状态还可以包含多个子状态,但大体来说,下面几种状态是通用的:

1)就绪:参与调度,等待被执行,一旦被调度选中,立即开始执行。

2)运行:占用CPU,正在进行中。

3)休眠:暂不参与调度,等待特定事件发生。

4)中止/终止:已经运行完毕,等待回收线程资源。

二、线程环境:

线程存在于进程之中,进程内所有全局资源对于内部每个线程都是可见的

进程内的典型全局资源如下

1)代码区:这意味着当前进程空间内所有的可见的函数代码,对于每个线程来说,也是可见的。

2)静态存储区:全局变量,静态空间。

3)动态存储区:堆空间。

线程内的典型局部资源如下:

1)本地栈空间:存放本线程的函数调用栈,函数内部的局部变量等。

2)部分寄存器变量:线程下一步要执行代码的指针偏移量。

一个进程发起后,会首先生成一个缺省的线程,通常称这个线程为主线程。C/C++程序中,主线程就是通过main函数进入的线程,由主线程衍生的线程成为从线程,从线程也可以有自己的入口函数,相当于主线程的main函数,这个函数由用户指定

通过thread类的构造函数传入函数指针来实现(如 std::thread task_1(func)),在指定线程入口函数时,也可以指定入口函数的参数,就像main函数有固定的格式要求一样,线程的入口函数也可以有固定的格式要求,参数通常都是void类型,返回类型根据协议的不同也不同,pthread中是void,winapi中是unsigned int,而且都是全局函数。

注意:最常见的线程模型中,除主线程较为特殊之外,其他线程一旦被创建,相互之间就是对等关系,不存在隐含的层次关系。每个进程可创建的最大线程数由具体实现决定。

注意:无论是在windows还是在posix中,主线程和子线程的默认关系是:无论子线程执行完毕与否,一旦主线程执行完毕退出,所有子线程执行都会终止。这时整个进程结束或僵死,部分线程保持一种终止执行但还未销毁的状态,而进程必须在其所有线程销毁后销毁,因此这时进程处于僵死状态

线程函数执行完毕退出,或以其他非常方式终止,线程进入终止状态,但是为线程分配的系统资源不一定释放,可能在系统重启之前,一直都不能释放。处于终止状态的线程,仍旧作为一个线程实体存在于操作系统中,什么时候销毁,取决于线程属性。在这种情况下,主线程和子线程通常定义以下两种关系:

1、可会合(joinable):在这种关系下,主线程需要明确执行等待操作。在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。

在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。

2、相分离(detached):表示子线程无需和主线程会合,也就是相分离的。在这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用

注意:

在任何一个时间点上,线程是可结合的(joinable)或者是可分离的(detached),一个可结合的线程能够被其他线程回收资源和杀死,在被其他线程回收前,它的存储器资源如栈,是不释放的。

相反地,一个相分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放

线程的分离状态决定一个线程以什么样的方式来终止自己,在默认的情况下,线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束,只有当pthread_join函数返回时,创建的线程才算终止,释放自己占用的系统资源,而分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源

注意:detach()的作用是将子线程和主线程的关联分离,也就是说detach()后子线程在后台独立继续运行,主线程无法再取得子线程的控制权即使主线程结束,子线程未执行也不会结束。当主线程结束时,由运行时库负责清理与子线程相关的资源。实际应用如让一个文字处理应用同时编辑多个文档,让每个文档处理窗口拥有自己的线程,每个线程运行同样的代码,并隔离不同窗口处理的数据。

detach()同时也带来了一些问题,比如子线程要访问主线程中的对象,而主线程中的对象又因为主线程结束而被销毁时,会导致程序崩溃。所以传递参数时需要注意一些陷阱。关于参数传递:【C++多线程】传递参数 - Chen沉尘 - 博客园  

  1、访问主线程对象以及指针问题;

  2、构造线程时隐式转换问题,子线程可能还来不及转换,主线程对象就销毁了,解决方法是               构造线程时,构造一个临时对象传入

参考:

(2条消息) c++11中thread join和detach的区别_Keep Moving~-CSDN博客_c++ detach

【C++多线程】detach()及注意 - Chen沉尘 - 博客园 (cnblogs.com)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值