我的GitHub:Powerveil · GitHub
我的Gitee:Powercs12 (powercs12) - Gitee.com
皮卡丘每天学Java
进程就是 任务,跑起来的程序 系统使用 PCB 描述进程,使用双向链表来管理进程
进程存在的意义就是让操作系统可以同时执行多个任务,从而实现“并发编程”(并发+并行)的效果 就可以充分的利用到 多核 CPU 资源
虽然多进程已经实现了并发编程了,但是存在重要的问题,如果频繁的创建/销毁进程,这个系统就比较低效
例如写一个服务器程序,就可以针对每个客户端分别创建一个进程,去提供服务
服务器这里可能又多个客户端,每次有个新的客户端来了,都要创建一个进程来服务,客户端走了,进程就销毁 进程创建销毁太频繁,效率是比较低的。
进程创建步骤:
-
创建 PCB
-
给进程分配资源(内存/文件),赋值到 PCB 中
-
把 PCB 插入链表
进程销毁的步骤:
-
把 PCB从链表上删除
-
把 PCB 中只有的资源释放
-
销毁 PCB
其中创建进程第二步分配资源,销毁进程中的第二步释放资源是比较消耗时间的,于是发明了线程。
线程是被包含在进程中的,一个进程默认会有一个线程,当然也可以有多个线程,每个线程都是一个 “执行流” 可以单独的在 CPU 上进行调度,同一进程中的这些线程公用一份系统资源(内存+文件)
所以线程 成为 “轻量级进程”,创建线程的开销比创建进程小,销毁线程的开销比销毁进程小。
使用多线程:
-
更够充分利用上多核 CPU,能够提高效率
-
只是创建一个线程的时候,需要申请资源,后序再创建新的线程都是共用一份资源(节省了申请资源的开销)销毁线程的时候,也只是销毁到最后一个的时候才真正释放资源,前面的线程销毁,都不必真释放资源
操作系统内核,是通过 PCB 来描述进程的 更准确的说法,是一组 PCB 来描述一个进程,每个 PCB 对应一个线程 一个进程至少有一个线程,也可以有多个。
这一组 PCB 的内存地址和文件描述符表其实是同一分东西,而 状态,上下文,优先级,记账信息则是每个 PCB (每个线程)自己有一份
进程是 资源分配 的基本单位
线程是 调度执行 的基本单位
一个非常重要的面试题:谈谈进程和线程之间的区别
-
进程包含线程
-
线程比进程更轻量,创建更快,销毁也更快
-
同一个今进程的多个线程之间共用同一份内存/文件资源,进程和进程之间则是独立的内存/文件资源
-
进程是资源分配的基本单位,线程是调度执行的基本单位
举个例子
需求:一个人要吃200只鸡
一、多进程方案
用两个房间,两套桌子,两个人,每个人吃100只即可,效率++,劣势也很明显,成本是比较高的,优势:两个人相互之间不会干扰
二、多线程
只是多叫一个人,成本低了,效率仍然能够提升,缺点:彼此之间可能会相互影响
三、继续增加人
当人的数量再次提高,效率仍然能上升
当人的数量进一步提升的时候,把桌子围满了,此时新增的人抢不到位置,此时效率无法继续提升了 而且,人们挤来挤去,导致正在吃的人正常吃鸡(影响效率)
对应到多线程上,线程数量也不是越多越好。CPU 核心数是有限的,当线程数目达到一定程度的时候,CPU 核心数就已经被吃满了,此时继续增加线程,也无法再提高效率,反而会因为线程太多,线程调度开销太大,影响效率。
四、线程之间可能会相互影响
两个人争抢一个鸡,发生争执
线程不安全,如果两个线程同时修改同一个变量,也容易产生“线程不安全”的问题
五、如果某个线程发生了意外,此时很可能就把整个进程带走(其他线程无法工作)
如果一个人吃着吃着不开心把桌子掀翻了,其他人都没有办法继续吃
如果某个线程执行过程中出现异常,并且异常没有处理好的话,整个进程都会随之崩溃,这个时候后序其他线程自然难以进程运行。
其实操作系统调度 PCB,每个 PCB 就是一个线程