进程与线程
进程与线程的由来
串行:一开始的计算机只能接收一些特定的指令,输入一个执行一个,这样效率很低
批处理:将需要执行的操作写成一个指令清单,让计算机按照清单上的指令执行
(计算机不断读取指令进行相应的操作,批处理操作系统诞生,计算机将指令清单写在一个磁带上,计算机读取指令进行相关操作,
将输出结果写在另一个磁带上)
批处理遇到的问题:
但是批处理操作系统遇到了一个问题:假设有两个任务A和B,A在执行一半时需要进行大量的数据输入,CPU只能等A读取完数据,才能继续执行下面的操作,
这样白白浪费了CPU资源;人们就想能否在任务A读取数据时,让任务B去执行,等任务A读取完数据,暂停任务B再执行任务A,但是这会有一个问题,就是原来
只有有一个程序在计算机中运行,也就是说内存中只有一个程序的运行数据,如果让A读取数据时,让B抢占CPU资源去执行,内存中必然要装有多个程序,如何处理
多个程序的数据,如何辨别当一个程序暂停后,它如何恢复之前执行的状态,此时进程对应而生,让进程对应一个程序,每一个进程对应一定的内存地址空间,它只能使用自己的
内存空间,各个进程之间互不干扰。
进程:进程保存了程序每个时刻运行的状态,这为进程间的切换提供了可能。进程暂停时,它会保存当前程序运行的状态,如进程标识,进程的使用资源等,
在下次切换过来时,根据之前保存的状态进行恢复,然后继续执行。进程为操作系统的并发提供可能。
并发从宏观上看有多个任务在执行,事实上对于单核CPU计算机来说,任意一个时刻只有一个任务在占用CPU资源,让用户看起来计算机在同时执行多个任务的原因,
是CPU分给单个任务的时间片很短,切换的频次高,造成所有任务都在并发执行的假象。
进程遇到的问题:
出现进程之后,操作系统性能大幅度提升,虽然进程的出现解决了操作系统的并发问题,但是随着人们对实时性有了更高的要求,进程在 一段时间内只能做一件事,
如果一个进程有多个子任务,只能逐个执行这些子任务,而往往这些子任务不存在顺序上的依赖,是可以并发执行的。
线程:既然CPU能按照时间片的方式轮流切换跑进程,能不能给这些子任务打个标签,让CPU按照更细的时间片去执行这些子任务呢?答案是肯定的。由于任务共享进程的内存等资源,
因此隶属同一个进程内的子任务之间的切换是页目录以使用新的内存空间,为子任务更快速的切换提供可能。因此发明了线程,让线程执行一个子任务。
一个进程包含多个线程,每个线程负责一个独立的子任务,以期达到提高实时性的效果。
进程为操作系统的并发性提供可能,进一步细分线程为进程的并发提供可能。
进程与线程的区别
(1)进程是资源分配的最小单位,线程是CPU调度的最小单位
线程就是来工作的,进程是拥有资源者
(2)进程可以看作一个独立的应用,而线程却不可以,线程可以看作是进程工作的最小单位
(3)进程有自己独立的内存地址空间,即不共享内存,并互不影响,线程只是进程的不同执行路径,线程没有独立的内存地址空间
同一个进程下的多个线程共享进程的地址空间
(4)进程间的切换比线程间的切换开销大
(5)线程在执行过程中,需要协作同步,不同进程的线程需要利用消息通信性能的办法实现同步
要控制好具体哪些数据归哪个线程在哪个时间段操作,不同进程通信通过消息队列,把数据消息扔到中间件
让另一个进程来读
java中进程与线程的关系
(1)java对操作系统中的进程和线程进行了封装
(2)一个java程序就是一个进程,一个进程中至少包含一个线程,每个线程都有自己私有的栈
(3)每个java进程对应一个JVM实例,每个JVM实例唯一对应一个堆,多个线程共享JVM里的堆
(4)java采用单线程编程模型,程序会自动创建主线程
(5)java程序中的主线程可以创建子线程,一般主线程最后完成执行
主线程的重要性主要体现在两个方面
(1)它是产生其他子线程的线程
(2)通常它需要最后完成执行,因为它需要执行各种关闭动作
在IO操作时,将耗时的操作放在子线程中,以避免阻塞主线程,影响用户体验。
进程类似于投资者,它们手握资源,而真正拿这些资源去投资的是线程。
进程与线程的优缺点
进程优点
每个进程互相独立,一个进程的崩溃并不影响其他进程
通过增加CPU,就可以扩充性能
可以尽量减少线程加锁与解锁的影响,极大提供性能
进程缺点
逻辑控制复杂,需要和主程序交互
多进程调度开销大
线程优点
程序逻辑和控制方式简单
所有线程共享内存和变量等
线程切换的消耗比进程小
线程缺点
每个线程与主程序公用地址空间,最大内存地址受限
线程之间的同步和加锁不易控制,容易出现死锁
一个线程的奔溃可能影响到整个程序的稳定性