同步和异步
同步就好比打电话,通信双方,你一句我一句,一句话得不到回应就会一直问:“喂?喂?可以听到么?是不是信号不好呀”。
异步就像发短信,发完短信我就去干点别的,看个视频、玩个游戏、干啥都行,等对方给我回信息了我再来处理短信(也可以不处理)。
线程和进程
进程的概念听起来很抽象,不大好理解。但是我知道你肯定认识这个东西,请看下图:
上方这些占用我的电脑CPU、内存、磁盘、网络的这些就都是进程。
那什么是线程呢?线程可以理解成是在进程中独立运行的子任务。比如微信运行时就会有很多的子任务在同时运行。比如,视频线程、下载线程、表情线程、语言线程等。简单来说,一组线程互相协作完成某一个程序的一些功能供我们使用。
并发和并行
- 并发和并行乍一看好像是一种东西,但是实际上区别很大。并发表示的是交替做不同事情的能力,而并行表示的是同时做不同事情的能力。例如你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这就是并发。你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这是并行。
- 我们常说的高并发系统就是说的并发而不是并行。
- 并不是所有的系统都可以实现并行,因为一个CPU一次只能执行一条指令,所以想要实现并行必须是多核才可以
临界资源
临界资源:是一次仅允许一个进程使用的共享资源。例如公共电话,一次只能一个人使用
临界区:每个进程中访问临界资源的那段代码叫做临界区。例如使用公共电话的人
阻塞
线程在试图执行代码前,会试图获取临界区的锁,如果得不到,线程就会被挂起等待,从而形成阻塞。
死锁
多个线程循环等待它方占有的资源而无限期地僵持下去的局面。例如两个人想要使用公共电话打电话,结果一个人抢到了话筒,一个人拨了号。两个人谁也不让谁,就会无休止地等下去从而引起死锁。
死锁产生的四大必要因素:
- 互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
- 占有且等待:一个进程本身占有部分资源,同时还有资源未得到满足,正在等待其他进程释放该资源。
- 不可抢占:别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
- 循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。
当以上四个条件都满足时才会发生死锁,所以想要避免死锁只要能破坏上方四个条件的任意一个都可以。
饥饿
线程因为优先级或其他原因始终无法获取到临界资源。例如A在使用公用电话在打电话,B来了之后在后面排队。之后C来了,一看认识A,好么,哥们你打完我来。然后D来了,他认识C。。。就这样B一直等待从而引起饥饿。
活锁
多个相互协作的线程为了彼此间的响应而相互礼让,使得没有一个线程能够继续前进,那么就发生了活锁。例如两个人在一个很宅的胡同里。一次只能并排过两个人。两人比较礼貌,都要给对方让路。 结果一起要么让到左边,要么让到右边,结果仍然是谁也过不去从而引起的活锁。
线程的并发级别
-
1. 阻塞:参见上方阻塞的定义
-
2. 无饥饿:对比上方的饥饿,如果设置所有线程的优先级相同,则任何想要获取资源的线程都要排队,那么所有的线程都有机会执行。
-
3. 无阻塞:所有线程一起修改临界资源,修改完成后读取该资源是否被其他线程修改,如被其他线程修改则进行回滚,然后进行重试。
-
4. 无锁:前面说的无阻塞是指所有的线程都能进入临界区,但如果发生了竞争,线程发现自己的数据每次去操作总是跟其它线程产生冲突,它就会不停地重试,如果在临界区当中有10个线程,线程1修改了部分数据,结果它被线程2干扰了,线程2又被线程3干扰,依此类推,最后线程1它又可能去干扰线程10,如果它们之间是彼此干扰的,最终会导致所有的线程都卡死在里面。而无锁在无阻塞的基础上加一个了约束,保证在竞争当中有一个线程是必然能够胜出的,这样就能保证在临界区的线程当中至少有一个是能顺利走出去的。当第一个线程走出去之后,就有第二个线程、第三个线程、等所有的线程都能走出去
-
5. 无等待:无等待相比于无锁更进一步,它保证所有线程能进并且至少有一个线程能出来的同时还要求
所有进入临界区的线程都能够在有限步当中完成其操作。
网友评论