进程存在的问题
进程的问题导致了线程的出现
多进程已经很好的实现了并发编程的效果,但是这里有个明显的缺点:进程太重了(消耗资源多,速度更慢),如果进程创建和销毁不频繁还好,一旦需要大规模频繁的创建和销毁进程,开销就比较大了–>需要给进程分配资源
一个处理办法,就是在创建进程的时候,只分配一个简单的pcb,而不去分配后续的这些内存硬盘资源(既能够并发的执行任务,又能够提升 创建/销毁的速度)–>这就是轻量级进程===>这就是线程(Thread)
线程解决进程问题
只创建了一个pcb,但是没有分配后续的,内存硬盘/资源
但是线程搞出来,是为了执行一些任务,执行任务有需要消耗这些硬件资源
解决方法: 创建的还是进程,创建进程的时候,把资源都分配好,后续创建线程的时候,让线程在进程内部创建(进程 和 线程之间的关系,可以认为是进程包含了线程),后续进程中的新的线程,直接复用前面进程这里创建好的资源
其实,一个进程,至少需要包含一个线程,最初创建出来的这个进程,可以视为是一个只包含一个线程的进程(此时创建的过程需要分配资源,此时第一个线程的开销可能是比较的),但是后续再在这个进程里面创建线程,就可以省略分配资源的过程,资源已经有了
可以理解成地皮还是同一块地皮(同一个进程),不过地皮(进程)中比原来多出了好多生产线(线程),这时候省了物流,工人,地(资源),并且两条生产线同时生产(并发)
进程与线程关系
- 使用多进程变身就可以完成并发编程,但是进程比较重,创建和销毁开销比较大(需要申请和释放资源)
- 引入线程,更高效的解决上述问题
- 所谓线程,也可以称为轻量级进程
- 一个进程可以包含多个线程,也可以包含多个线程
- 这个进程中的多个线程,共同复用了进程中的各种资源(内存,硬盘)
- 但是这些线程各自独立的在cpu上进行调度(实现了并发),因此线程既可以完成并发线程的效果,又可以以比较轻量的方式来运行
- 描述线程,同样也通过pcb描述(linux上相同,但是windows是分开的),linux开发者比较懒复用了pcb这个结构体来描述线程,此时,一个pcb对应到多个线程,多个pcb对应到一个进程
- pcb(线程和进程)中的内存指针,文件秒速符,同一个进程的多个pcb,这两个字段都是一样的,但是上下文,状态,优先级,记账信息,支持调度的属性,这些pcb则每个人的都不一样
线程/进程代表的含义
- 同一个进程中的这些线程共用一份资源,但是每个线程又独立去cpu上调度(状态,上下文,优先级,几张信息…各自有各自的一份)==>进程,是操作系统进行资源分配的基本单位,线程是操作系统进行调度的执行的基本单位
线程存在的问题
- 但是线程个数也要有节制,一点是资源问题,一点是cpu的逻辑核心数就那么点,每个线程都会单独消耗cpu的逻辑核心(不是物理核心),线程太多导致线程调度开销太大,反而拖慢整个进程效率
- 线程多了都想占用某块资源,导致起了冲突,就会造成bug,这就造成了"线程安全问题"
- 一旦某个线程,执行出现异常,并且这个异常没有很好的处理,此时就可能导致整个进程直接终止(导致进程中的所有线程也随之全部终止)
- 算但多线程编程 相比于 多进程编程,确实有优势(更轻量,创建销毁速度更快),但也有缺点(不像进程那样稳定,容易一个线程出问题导致其他线程都出问题)
进程/线程 总结
- 进程包含线程,都是为了实现并发编程的方式,线程比进程更轻量
- 进程是系统分配资源的基本单位,线程是系统调度执行的基本单位.创建进程的时候把分配资源的工作给做了(虚拟地址空间,文件描述符表),后续创建线程,直接公用之前的资源即可
- 进程有独立的地址空间,彼此之间不会相互影响到,进程的独立性=>系统稳定性提高
- 多个线程公用这份地址空间,一个线程一旦抛出异常,就可能导致整个进程异常结束=>多个线程之间容易相互影响
- 进程和线程的结构体都是pcb
进程的再轻量化
线程是更轻量了,但是也不是没有成本,高并发的服务器是非常多的,要处理的并发量太多了,非常频繁的创建线程/销毁 线程,开销仍然不可忽视,这时候就发明了"轻量化线程"==>协程/纤程 或者运用 线程池(要释放的资源不急着释放,先放到池子里,以备后续使用,申请资源的时候,也提前把资源申请好,也放到池子里,后续申请的时候也比较方便)
线程 与 OS
线程本身是操作系统提供的概念,操作系统也提供了一些API供程序员使用(Linux,pthread)
java中,就把操作系统的API有进行了封装,提供了Thread类(直接使用这个类就可以完成多线程编程)
多线程 是每个线程都能被独立调度