进程和线程区别
概述
看了一遍排在前面的答案,类似”进程是资源分配的最小单位,线程是CPU调度的最小单位
“这样的回答感觉太抽象,都不太容易让人理解。
区别
做个简单的比喻:进程=火车,线程=车厢
- 线程在进程下行进(单纯的车厢无法运行)
- 一个进程可以包含多个线程(一辆火车可以有多个车厢)
- 不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
- 同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
- 进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
- 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
- 进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
- 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-“互斥锁”
- 进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”
百度
根本区别
根本区别:进程是资源分配最小单位,线程是程序执行的最小单位。 计算机在执行程序时,会为程序创建相应的进程,进行资源分配时,是以进程为单位进行相应的分配。每个进程都有相应的线程,在执行程序时,实际上是执行相应的一系列线程。
地址空间
地址空间:进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段;线程没有独立的地址空间,同一进程的线程共享本进程的地址空间。
资源拥有
资源拥有:进程之间的资源是独立的;同一进程内的线程共享本进程的资源。
执行过程
执行过程:每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
单位
线程是处理机调度的基本单位,但是进程不是。由于程序执行的过程其实是执行具体的线程,那么处理机处理的也是程序相应的线程,所以处理机调度的基本单位是线程。
系统开销
系统开销:进程执行开销大,线程执行开销小。
死锁
条件
当且仅当以下四个条件同时成立时,死锁才会发生:
-
互斥。同一个资源在同一时刻最多只能被一个进程占用。
-
占有并等待。必然有一个进程至少占用了系统中的一个资源,同时在等待获取被其他进程占用的资源。
-
不可剥夺。一个进程不能剥夺被其他进程占用的资源。
-
循环等待。在等待图中有一个循环。
死锁的处理基本策略和常用方法。
解决死锁的基本方法如下:
预防死锁、避免死锁、检测死锁、解除死锁
预防死锁:
-
资源一次性分配:(破坏请求和保持条件)
-
可剥夺资源:即当某进程新的资源未满足时,释放已占有的资源(破坏不可剥夺条件)
-
资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
避免死锁:
预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得 较满意的系统性能。由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。
检测死锁
首先为每个进程和每个资源指定一个唯一的号码;
然后建立资源分配表
和进程等待表
解除死锁:
当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:
-
剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
-
撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。
解决四多的常用策略如下:
鸵鸟策略、预防策略、避免策略、检测与解除死锁
如果你对死锁的处理策略不是太熟悉,推荐阅读:产生死锁的原因和必要条件+解决死锁的基本方法https://blog.csdn.net/bxyill/article/details/8237339
进程(Linux)间的通信方式
1、管道
管道,英文为pipe。这是一个我们在学习Linux命令行的时候就会引入的一个很重要的概念。它的发明人是道格拉斯.麦克罗伊,这位也是UNIX上早期shell的发明人。他在发明了shell之后,发现系统操作执行命令的时候,经常有需求要将一个程序的输出交给另一个程序进行处理,也因此,管道应运而生了。
管道可以分为两类:匿名管道和命名管道。
常见的Linux命令 “|” 其实就是匿名管道,表示把一个进程的输出传输到另外一个进程
2、消息队列
注意,此消息队列不是我们常用的MQ,如kafka,rabbitmq,rocketmq等。
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
使用消息队列进行进程间通信,可能会收到数据块最大长度的限制约束等,这也是这种通信方式的缺点。如果频繁的发生进程间的通信行为,那么进程需要频繁地读取队列中的数据到内存,相当于间接地从一个进程拷贝到另一个进程,这需要花费时间。
3、共享内存
共享内存这个通信方式就可以很好着解决拷贝所消耗的时间了。系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分却是映射到相同的物理内存,这就完成了内存共享机制了。
4、信号量
共享内存最大的问题是什么?没错,就是多进程竞争内存的问题,就像类似于我们平时说的线程安全问题。如何解决这个问题?这个时候我们的信号量就上场了。
信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是 1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1。所以说,信号量也是进程之间的一种通信方式。
5、Socket
这个就是我们一直在用的进程间的通信方式了,如我们的微信APP跟微信服务器通信,其实就是使用的Socket套接字进行通信的。
https://www.cnblogs.com/happy4java/p/11343072.html
页式管理内存是指什么呢?
在分页系统下,一个程序发出的虚拟地址由两部分组成:页面号和页内偏移值。为了解决程序比内存大的问题,我们可以允许一个进程的部分虚拟页面存放在物理页面之外,也就是磁盘上。在需要访问这些外部虚拟页面时,再将其调入物理内存,需要腾出空间时,将暂时不同的内存swap到磁盘。
虚拟内存是指什么呢?
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换
虚拟内存到物理内存是怎么实现的呢?
总结: 对于一个内存地址转换,其实就是这样三个步骤:
- 把虚拟内存地址,切分成页号和偏移量的组合;
- 从页表里面,查询出虚拟页号,对应的物理页号;
- 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。
原文链接
线程和进程的区别是什么?
https://www.zhihu.com/question/25532384/answer/411179772
进程间通信方式总结
https://www.cnblogs.com/happy4java/p/11343072.html
常见面试题整理–操作系统篇(每位开发者必备)
https://zhuanlan.zhihu.com/p/23755202?refer=passer
其他博客
一篇让你明白进程与线程之间的区别与联系
https://www.cnblogs.com/coder-programming/p/10595804.html
进程与线程的区别?
https://jingyan.baidu.com/article/11c17a2cf213eff446e39d1d.html