1. 先认识一下大背景:进程(Process)
要搞懂线程,必须先知道“进程”。如果你在电脑上双击打开了微信,又双击打开了QQ。
在计算机眼里,这就启动了两个“进程”。
生活比喻:你可以把“进程”想象成两家独立的餐厅。微信是一家专门做通讯的餐厅,QQ是一家专门做社交的餐厅。两家餐厅互不干扰,微信卡死了,完全不影响QQ继续运行。
2. 什么是线程(Thread)?
现在,咱们把目光聚焦到其中一家餐厅(比如微信这家餐厅)。
这家餐厅要运转,需要做很多事情:接收消息、发送朋友圈、加载图片、播放语音……
如果全餐厅只有一个服务员(或厨师),他只能一件事一件事地干:先收消息,收完去发朋友圈,发完再去加载图片。这就叫单线程。
但如果这家餐厅里有好几个服务员(或厨师),他们可以同时干活。张三负责接客,李四负责炒菜,王五负责收银。他们虽然都在同一家餐厅里,但各自做着不同的事。
专业定义:这就是线程!线程是程序执行的最小单位。
生活比喻:线程就是餐厅里的“服务员”或“流水线”。
总结一下关系:
进程是“餐厅”,线程是“餐厅里的员工”。
一家餐厅(进程)可以雇一个员工(单线程),也可以雇十个员工(多线程)。员工们共享这家餐厅的场地和食材。
3. 生活中的“线程”硬核实战例子
为了让你彻底弄懂,咱们再看两个你每天都在经历的例子:
例子一:用电脑边听歌边打游戏(并发与上下文切换)
你在用电脑玩《英雄联盟》,后台还开着网易云音乐放歌。
单核CPU(只有一个店长):其实你的CPU(处理器)核心数往往不多,它就像只有一个超级店长。店长非常忙,他看一眼游戏(操作角色放个技能),马上切过去看一眼音乐播放器(加载下一首歌)。
上下文切换:因为店长切换速度太快了(一秒钟切换几十亿次),你感觉不到卡顿,觉得游戏和音乐是“同时”进行的。这在计算机里叫“上下文切换”。
例子二:去银行办业务(多线程的锁与排队)
一家银行(进程)开了 3 个窗口(3个线程)。
共享资源:3个窗口的柜员,共用同一个厕所、同一台叫号机。
死锁(Deadlock):如果窗口A的柜员拿着唯一的厕所钥匙去打印,窗口B的柜员拿着唯一的打印纸去上厕所,两人都不肯让步,结果谁也办不成。这就是计算机里可怕的线程死锁。
排队(同步):如果3个窗口同时想用同一台打印机,系统就会说:“排队!”这就是线程锁。
4. 为什么我们需要“多线程”?
如果单线程(一个人干活)也能把事干完,为什么计算机非要多线程(雇一堆人)呢?
为了快(提高效率):下载一部电影,单线程就像是只有一条水管在放水,慢吞吞的。多线程就像是接了10条水管同时放水,速度瞬间起飞。
为了不卡(防止界面假死):假如你的Word文档是个单线程程序,当你在疯狂打字时,Word如果去执行“自动保存”(保存需要几秒钟),这个时候你按任何键它都不会理你(假死)。有了多线程,一个线程专门管让你打字,另一个线程在后台悄悄保存,你完全没感觉。
5. 员工(线程)越多越好吗?
既然是好事,那软件是不是雇一万个线程越好?
绝对不是。
管理成本增加:一家小饭店如果雇了100个厨师,厨房根本站不下,光是互相避让的时间,就够炒好几盘菜了。计算机也一样,线程越多,CPU光是决定“接下来该让谁干活”的调度成本就会剧增,反而变慢。
容易抢资源:线程太多,大家都去抢同一个网络、同一块内存,容易造成冲突,甚至互相把对方锁死。
💡 给学生的“一句话通俗总结”
程序:是你手里的一本菜谱(静态的)。
进程:是你把这本菜谱拿去开了一家餐厅(动态的,占着场地和食材)。
线程:是餐厅里跑堂传菜的服务员(实际干活的)。
多线程:就是雇了一群服务员,让他们各司其职、默契配合,让餐厅运转飞快,同时还要防止他们因为抢工具而打架。
希望这个“餐厅”的例子,能让你在以后听到“多线程”、“并发编程”这些词的时候,脑海里立刻浮现出一个热火朝天但又井井有条的后厨画面!