0. 前言
关于多线程需要理解的一些基本的概念,为了防止打代码打到阿尔兹海默症,写下几个抖机灵的 🌰 ...
1. 进程和线程
进程是什么
进程可以理解为一个正在运行的的程序,各个进程之间是相互独立的。
线程是什么
线程是进程运行过程中的执行路径。每一个进程想要运行,都需要至少一个线程来确定代码的执行路径。
然后呢…
举个栗子,手机里的微信和QQ在运行的时候,都是 iOS 系统中的进程。当你打开微信,给你的好基友发了一条 60 秒的语音信息,在你松开手之后,你想给他发一个表情 🙄️,所以你点击对话框输入 🙄️。
如果发语音和对话框输入必须按照顺序进行,也就是说这两个动作必须按顺序走,那么万一你所处环境网络状态很差,你就需要等这 60 秒语音完全用渣网络发完之后,你才能够点得动对话框来输入。我相信这个时候你已经把手机砸了...
所以呢…
所以,这就是多线程的必要性啊...
2. 串行、并行和并发
串行是什么
串行是指在同一时间点,只执行一个任务。比如只有一个 CPU,只能跑一条线程。
并行是什么
并行是指在同一时间点,同时执行多个任务。比如有两个 CPU,可以同时跑两条线程。
并发是什么
并发是指在同一时间点,有执行多个任务的能力。比如只有一个 CPU,但是可以非常快速地在两条线程上切来切去,看起来像是同时跑两条线程。
用人话来说
冰雪消融,万物复苏,春天来了,又到了撸串的时候,我们能看到老板把 1 块羊肉穿进串,再把 1 块软骨穿进串,接着是 1 块彩椒… 循环 1...8 次,返回 2 串骨肉相连。这是串行。
又双到了撸串的时候,比较牛逼的老板手里可以拿 2 根签子,同时串 2 块羊肉,再是 2 块软骨,接着 2 块彩椒… 循环 1...4 次,返回 2 串骨头相连。这是并行。
又双叒是撸串的时候,发现老板一手握起两个签子… 大概是这样 —👊—
然后,穿 1 块羊肉,唰,手非常快速地转到另一头,穿 1 块羊肉,唰,手又非常快速地(🙄️)转到另一头… 循环 1...4 次,返回 2 串骨肉相连。这是并发。
3. 同步和异步
同步是什么
同步方法是完成任务之后返回,控制权交回给方法调用者,同时给结果。
异步是什么
异步方法是任务开始就立即返回,控制权马上回归方法调用者,结果在需要时由掌权者去拿。
人话
同步就是我给你一张纸条,上面写着买 7 杯冰美式给我
,你把纸条拿去,买了 7 杯冰美式回来,同时把纸条还给我。
异步就是我给你一张纸条,上面写着买 7 杯冰美式放到前台
,你看完把纸条还给我,买了 7 杯冰美式放到了前台,我需要的时候再去前台拿。
4. 队列
顺序队列
- - - 任务1
我是任务2
我任务3
- - -
并发队列
- - - 任务1
- - - - - - - - - - - - - - - - - - - - -
- - - - - - 我是任务2
- - - - - - - - - - - - - - -
- - - - - - - 我任务3
- - - - - - - - - - - - - - - -
5. 其他
临界区
不能并发执行的代码。比如说你口袋里有 1 个硬币,左手知道有 1 个硬币所以想拿 1 个,同时右手也知道有 1 个硬币也想拿 1 个。如果左手拿了 1 个,右手就没得拿,但它又是被告知口袋里有 1 个硬币,然后就一直找一直找,最后,右手卒。反之,左手卒。
线程安全
能够并发执行或者多个线程同时调用的代码。比如说你口袋里有 1 个硬币,不能拿只能摸(...),左手想摸 1 个硬币,同时右手也想摸 1 个硬币,然后它们都摸到了...
互斥锁
给临界区加锁,保证一次只能有一个线程调用。
死锁
两个或两个以上的线程,因为要等待彼此任务的完成而陷入双方或多方均不能继续进行的困境。也就是经常在交叉路口四辆车互不退让的情况。