进程与线程
Posted Frey_Liu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程与线程相关的知识,希望对你有一定的参考价值。
对比
进程是计算机系统资源分配的最小单元,进程为线程提供资源。一个进程中可以有多个线程,同一个进程中的线程可以共享进程中的资源。
线程是计算机可以被CPU调度的最小单元。
进程不局限于一段可执行的程序,还包括资源,打开的文件、挂起的信号、内核内部的数据、处理器状态、如地址空间、全局数据段、多线程。
每个线程拥有独立的程序计数器、进程栈和一组进程寄存器。
类比进程与线程:
- 一个工厂,至少一个车间,每个车间至少一个工人,最终工人进行工作!
- 一个程序,至少一个进程,每个进程至少一个线程,最终线程进行工作!
通常,计算密集型,利用多核优势,适合多进程; IO操作更适合多线程。
随着应用程序功能设计的越来越复杂,应用程序中的某种活动可能被阻塞,自然而然的想着能不能把这些应用程序分解成更细的粒度,能“并行”的执行多个执行实体,并且这些细粒度能够可以共享程序的地址空间,也可以共享程序代码、数据及内存空间,线程就被引入了。
另外一个引入线程的原因,每个进程都有独立的代码和数据空间(程序上下文),程序之间切换会开销很大,而线程之间共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器,线程之间的切换开销小。
引入线程模型后,进程负责分配和管理系统资源,线程负责调度运算,也是CPU切换时间片的最小单位,创建进程后会有默认一个主线程的。
进程与线程的区别总结:
- 区别:进程是操作系统资源(CPU、内存)分配的基本单位,而线程是处理器任务调度和执行的基本单位。
- 关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。一个进程崩溃后,在保护模式下其他进程不会被影响,但是一个线程崩溃可能导致整个进程被操作系统杀掉,所以多进程要比多线程健壮。
- 开销:每个进程都有独立的地址空间和数据空间(各个进程间内存地址相互隔离),进程之间的切换会有较大的开销;线程可以看做轻量级的进程,同一个进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
- 通讯:进程需要跨进程边界,适合小数据量传送,线程间适合大数据量传送。进程间:管道、信号、共享内存、消息队列、限号量、socket。线程间:信号量、读写锁、条件变量、互斥锁。
- 上下文切换:有进程上下文、中断上下文,需要保存当前任务的运行环境,恢复将要运行任务的运行环境(程序指令运行的位置,寄存器、堆栈)。进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
Linux而言,对进程线程并不特别区分,线程仅视为一个与其他进程共享资源的进程,在调用clone()创建线程时需要传递一些参数标志来指明父子需要共享的资源。
传统的进程就像一个MCU,RTOS创建的Task就像创建的线程,TASK可以共享MCU(没有MMU)。
进程切换与线程切换
-
进程切换
切换虚拟地址空间,切换内核栈和硬件上下文 -
线程切换
切换内核栈和硬件上下文
详见 进程切换与线程切换
多线程与超线程
参考:什么是超线程?
-
多线程是并行化的一种形式,或者是拆分工作以便同时进行处理。线程化的程序将工作拆分到多个软件线程,而不是将大量工作交给单个内核。这些线程由不同的 CPU 内核并行处理,以节省时间。
-
超线程如何工作?当英特尔® 超线程技术处于激活状态时,CPU 会在每个物理内核上公开两个执行上下文。这意味着,一个物理内核现在就像两个“逻辑内核”一样,可以处理不同的软件线程。例如,当启用超线程时,10 核英特尔® 酷睿™ i9-10900K 处理器会有 20 个线程。
较之传统的单线程内核,两个逻辑内核可以更有效地完成任务。英特尔® 超线程 (HT) 技术充分利用了内核以前在等待其他任务完成时的空闲时间,提高了 CPU 吞吐量(在服务器应用程序中可提升 30%3)。
协程
协程是用户态内核的内核上下文切换技术,实现一个线程内部实现并发操作,比如contiki操作系统创建的process中广泛用了protothread。
线程池
线程池是一种使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务的办法。核心逻辑是提前创建好若干个线程放在一个容器中。如果有任务需要处理,则将任务直接分配给线程池中的线程来执行就行,任务处理完以后这个线程不会被销毁,而是等待后续分配任务。同时通过线程池来重复管理线程还可以避免创建大量线程增加开销。
使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存 或者“过度切换”的问题(如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间)。
为什么要用线程池
- 降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控
参考:
线程池原理及C语言实现线程池;
基于C++11实现线程池的工作原理;
进程池
创建适当的进程放入进程池,用来处理待处理事件,处理完毕后进程不销毁,仍然在进程池中等待处理其他事件,直到事件全部处理完毕,进程退出。 进程的复用降低了资源的消耗。
参考:
c语言进程池原理及实现;
Python-进程-进程池-原理;
进程锁与线程锁
linux线程同步和进程同步的区别;
线程的几种锁及基本操作;
以上是关于进程与线程的主要内容,如果未能解决你的问题,请参考以下文章