并发的本质:线程与进程区别

关注我,可了解更多有趣的面试相关问题。
本篇收录于《offer快到碗里来》

写在之前

"进程和线程有何区别?"

这个问题是校招面试中最最常见的问题了。很多人讨厌这种背诵课本概念的问题,还请看管打住,稍后再喷;该问题还真是一个值得思考的问题。

我们常常挂在嘴边的,你有没有经历过什么高并发项目,有没有比较难以解决的高并发问题。面试时,如果说没有遇到高并发问题似乎低人一等。

既然说到高并发,为啥会有高并发引发的各种问题呢?

本篇待我讲解了线程和进程有何区别,大家再来考虑为何高并发情况下线程安全问题。

最初的计算机时代

也许今天大家对于一个手机既能够刷抖音,又可以逛微博,还可以看***等能力习以为常,但是要知道最初的计算机可是长这样的。

初代计算机

如此大体积的机器,能够计算的能力还不及今天的笔记本。并且最初计算机只能接受一些特定的指令,用户输入一个指令,计算机就做一个操作。用户没有输入,计算机则会等待,用户和计算机总有一个在等待。

后来为了解决这个问题,提出了批处理 思路。用户可以将需要执行的多个程序写在磁带上,然后交由计算机去读取并逐个地执行这些程序,并将输出结果写到另一个磁带上。

但是这样还是有一个问题,如果计算机同时执行两个任务呢,比如一个程序A计算大象有多重,一个程序B计算熊猫有多少根毛,这个过程中计算机需要等待用户的输入(多次I/O操作),计算机只能等待所有的输入好了,再进行计算。这就导致了CPU的浪费。 (CPU又不怕累,闲着干啥)

后续计算机前辈们再想:能否在 任务A 读取数据的过程中,让 任务B 去执行,当 任务A 读取完数据之后,让 任务B 暂停,然后让 任务A 继续执行?反正就一句话,CPU别想偷懒。

但是这样又有一个问题?

在计算机内存中只能保存一份运行中的数据,两个程序相互切的时候如何能够知道彼此上一步计算到哪一步了呢。

为什么需要进程

天才们又发明了进程,让每个进程都有一定的内存地址空间,并且只能使用它自己的内存空间,各个进程间互不干扰。

并且进程可以保存自己的运行状态,这样就为进程切换提供了可能。当进程暂停时,它会保存当前进程的状态(每个进程都有独立的地址空间、堆栈、程序计数器等),在下一次重新切换回来时,便根据之前保存的状态进行恢复,然后继续执行。

举个例子:大家一会在抖音看小姐姐视频,一会儿回女朋友消息,回完了消息,还可以继续在原地方看小姐姐视频。

虽然直观感受上是同时进行的,但是其实同一个时间范围内只能有一个进程在占用一个CPU,只不过CPU执行太快了,导致用户以为是同时进行的。这就是并发,能够让操作系统从宏观上看起来同一个时间段有多个任务在执行。

为什么需要线程

上述听起来似乎一切都很美好,但是人类对于快的追求是无止尽的。爱折腾的计算机专家又在想:一个进程在一个时间段内只能做一件事情,如果一个进程有多个子任务,能不能让这些任务也分开执行呢?让cpu片刻不得休息。

于是人们又发明了线程每个线程都可以去执行一个子任务,这样一个进程就包括了多个线程,每个线程负责一个独立的子任务。

既然是在 一个进程内,那么多个线程必然共享了进程的独立地址空间或者说数据空间,每个线程控制自己的任务变量(程序计数器)和栈信息(存储各任务的变量信息)

线程让进程中的内部并发成为了可能。

线程引发的问题

可以看到多个线程共享了数据空间(内存),那么又会存在一个问题: 如果多个线程要同时访问某个资源,怎么处理?

比如,有一个花名册上面写了每个人的信息,张三想把自己的数学成绩由61改成99,李四想故意做坏,想把张三数据改得更低,由61改成59,王五更加丧心病狂,想直接删除张三的成绩(好家伙,缺德呀),多个人该同一份数据,如果同时发生,计算机怎么知道该执行谁的命令呢?

这也就是人们考虑的线程安全问题。

你说线程带来的问题大不大?肯定是大的。
但是你要说值得吗?
我觉得是值得的。

因为引入线程带来的收益造福的更多的人,总不能都2021年了,你的电脑做一些复杂的运算还是龟速吧。至于引发的线程问题,那就是coder们的事儿了。如何写出线程安全的代码,那就是各位看官该考虑的事儿了。

总结

总结一下什么是线程?什么是进程?

  1. 进程有自己独立的资源和地址空间,而线程可以与其他线程共享资源和内存,每个线程都有各自的 程序计数器 、 栈 以及 局部变量 等等。
  2. 进程是对运行时程序的封装,可以保存程序的运行状态,实现操作系统的并发;
  3. 进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能;
  4. 进程是操作系统资源的分配单位,线程是CPU调度的基本单位;
  5. 线程的引入导致了线程安全问题。

如有错误,还望不吝赐教。

参考:
《Java 并发编程实战》
《Java并发编程艺术》
《深入理解计算机系统》

全部评论

相关推荐

02-07 12:06
已编辑
华侨大学 测试开发
最近看到很多 92 的,甚至是硕士,开始往测开赛道卷,说实话有点看不懂。先把话说清楚,大厂里的测开,绝大多数时间干的还是测试的活,只是写点自动化脚本、维护测试平台、接接流水线,真正像开发一样做系统、做架构、做核心平台的测开少得可怜,基本都集中在核心提效组,而且人很少,外面进去的大概率轮不到你,我想真正干过人都清楚。很多人被洗脑了,以为测开也是开,和后端差不多,只是更简单、更轻松、还高薪。现实情况是,测开和开发的职业路径完全不一样。开发的核心是业务和系统能力,测开的核心是稳定性和覆盖率,前者是往上走,后者天花板非常明显。你可以见到很多开发转测开,但你很少见到干了几年测开还能顺利转回开发的。更现实一点说,92 的高学历如果拿来做测开,大部分时间就是在做重复性很强的杂活,这种工作对个人能力的放大效应非常弱。三年下来,你和一个双非的,甚至本科的测开差距不会太大,但你和同龄的后端、平台开发差距会非常明显。这不是努不努力的问题,是赛道问题。所谓测开简单高薪,本质上是把极少数核心测开的上限,当成了整个岗位的常态来宣传。那些工资高、技术强的测开,本身就是开发水平,只是挂了个测开的名。普通人进去,99% 做的都是项目兜底型工作,而不是你想象中的平台开发。测开不是不能做,但它绝对不是开发的平替,也不是性价比最优解。如果你是真的不想做开发,追求稳定,那测开没问题。但如果你只是觉得测开比后端容易,还能进大厂,那我劝你冷静一点,这只是在用短期安全感换长期天花板。有92的学历,如果你连测开这些重复性工作都能心甘情愿接受,那你把时间精力用在真正的开发、系统、业务深度上,回报大概率比卷测开要高得多。想清楚再下场,别被岗位名和话术带偏了,就算去个前端客户端也是随便占坑的,测开是一个坑位很少赛道,反而大面积学历下放,不用想也能知道会是什么结果,我想各位在JAVA那里已经看到了
烤点老白薯:测测你的
点赞 评论 收藏
分享
评论
2
8
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务