1、什么是线程
- 在⼀个程序⾥的⼀个执⾏路线就叫做线程(thread)。更准确的定义是:线程是“⼀个进程内部的控制序列
- ⼀切进程⾄少都有⼀个执⾏线程
- 线程在进程内部运⾏,本质是在进程地址空间内运⾏
- 在Linux系统中,在CPU眼中,看到的PCB都要⽐传统的进程更加轻量化
- 透过进程虚拟地址空间,可以看到进程的⼤部分资源,将进程资源合理分配给每个执⾏流,就形成了线程执行流
2、线程的优点
1、因为叫轻量化进程,自然也就比创建一个进程所消耗的更少。并且在线程之间切换和进程切换之间更快
2、进程切换要换多换CR3和TLB(快表)和 cache(代码和数据的缓存区。--概率,局部性原理,cache本质是缓存->预加载)
3、线程占用资源更少
4、计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
5、I/O密集型应用,为了提高性能,将I/0操作重参。线程可以同时等待不同的I/0操作
3、线程缺点
- 性能损失
- ⼀个很少被外部事件阻塞的计算密集型线程往往⽆法与其它线程共享同⼀个处理器。如果计
- 算密集型线程的数量⽐可⽤的处理器多,那么可能会有较⼤的性能损失,这⾥的性能损失指的是增加了额外的同步和调度开销,⽽可⽤的资源不变。
- 健壮性降低
- 编写多线程需要更全⾯更深⼊的考虑,在⼀个多线程程序⾥,因时间分配上的细微偏差或者因共享了不该共享的变量⽽造成不良影响的可能性是很⼤的,换句话说线程之间是缺乏保护的。
- 缺乏访问控制
- 进程是访问控制的基本粒度,在⼀个线程中调⽤某些OS函数会对整个进程造成影响。
- 编程难度提⾼
4、线程异常
• 单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃
• 线程是进程的执⾏分⽀,线程出异常,就类似进程出异常,进⽽触发信号机制,终⽌进程,进程
终⽌,该进程内的所有线程也就随即退出
5、线程⽤途
• 合理的使用多线程,能提⾼CPU密集型程序的执⾏效率
• 合理的使⽤多线程,能提⾼IO密集型程序的⽤⼾体验(如⽣活中我们⼀边写代码⼀边下载开发⼯
具,就是多线程运⾏的⼀种表现)
6、Linux进程VS线程
进程是资源分配的基本单位
线程是调度的基本单位
线程共享进程数据,但也拥有⾃⼰的⼀部分数据:
- 线程ID
- ⼀组寄存器
- 栈
- errno
- 信号屏蔽字
- 调度优先级
进程的多个线程,很多书都说线程有独立栈,但是其实其它线程想访问也是能做到的,所以线程大多数都是共享的
- ⽂件描述符表
- 每种信号的处理⽅式(SIG_IGN、SIG_DFL或者⾃定义的信号处理函数)
- 当前⼯作⽬录
- ⽤⼾id和组id
7、操作
轻量级进程的系统调用:vfork 最终的使用是系统调用clone(不用,太复杂)
库函数-用户级线程:pthread_create (线程id,线程属性,函数指针,喂给线程函数的参数) 返回值成功为0,失败为错误码;
c++11 : thread 本质是封装了pthread
所以编译都要包含pthread第三方库
新线程和main线程谁先运行不确定
线程创建出来,时间片也要瓜分,比如一个进程10hs,创建了5个线程,瓜分10hs,每个2毫秒
等待
线程创建的时候也是要被等待和回收的
理由:a.类似僵尸进程的问题 b.为了知道新线程的执行结果
等待 pthread_join(指定线程id,返回值二级指针); 阻塞等待
线程之间的大部分都是共享的,栈堆都可以
退出
主线程结束,进程结束,新线程结束,线程结束。
任何地方调用exit表示进程退出。
线程有取消的函数,但是不建议取消,因为不知道线程的状态取消了的返回值是-1
同时如果主线程有任务的话,可以将新线程设为分离状态,就可以不用等待子线程了。
线程取消也必须得join,否则会陷入类似僵尸
线程没有非阻塞等待
软件大多都不退