210101:并发
本文对“并发”这个概念做了精准定义。看过许多来源于百度的相关文章,我认为有些作者对于此概念的理解非常不到位,甚至是错误的。读完本文后,若您感觉有些帮助,请点赞;若您感觉有大帮助,给点赏金。
术语解释:线程(thread)
CPU用于执行指令,既然有指令,就有相应的数据。线程提供指令与相应的数据给CPU。可以形象地将线程理解为“生产者”,将CPU理解为“消费者”。
术语解释:时间片(time slice)
线程轮流使用CPU,究竟哪个线程占用CPU由线程调度算法决定。线程1获得CPU的使用权,意味着接下来的一段时间,CPU将执行线程1所提供的那些指令。线程调用算法分配给线程的那段时间被称为时间片。时间片耗尽后,线程1若未执行完,也不能继续“霸占”CPU了。接下来哪个线程使用CPU由线程调用算法决定。
术语解释:线程的生命周期
线程包含一条又一条指令,线程的执行本质上是其所包含的指令的执行。对于线程,某些情况下,仅仅一个时间片是不够用的。线程的生命周期指的是其包含的第一条指令开始执行的时间点,一直到最后一条指令执行完毕的时间点。请注意:某线程的生命周期不仅包含线程调度算法分配给它的时间片,也可能包含分配给其它线程的时间片,只不过对于这些时间片,此线程处于“挂起”状态。换句话说,对于两个线程,对应的生命周期有可能是重叠的。
术语解释:时钟频率(clock rate)
时间片的长度由时钟频率决定,时钟频率可进行设置。时钟频率越高,时间片越短。时钟频率是衡量CPU性能的重要指标。对时钟频率的解释到此为止,不能再深入了,学有止境。
术语解释:并发
并发这个概念,广泛存在于与计算机科学相关的知识领域中。并发描述了两个线程之间的关系。若线程1与线程2的生命周期重叠了,那么我们说这两个线程是并发的。
术语解释:并发控制
若具有并发关系的两个线程所访问的内存空间并不重叠,那么不会出现异常;若具有并发关系的两个线程所访问的内存空间重叠了,有可能出现异常。话讲到这,总结如下:对于两个线程,若“时间重叠”且“空间重叠”,那么异常有可能发生。所谓的并发控制就是通过某些措施杜绝异常的发生。异常发生的必要前提是“两个重叠”。
关于“两个重叠”的案例
线程1占据时间片1与时间片4;线程2占据时间片2与时间片3。线程1的工作是使得某账户余额(初始值1000)减去100,线程2的工作是使得此账户余额增加100。假设时间片1结束时,线程1未将结果(900)写入(账户余额对应的)内存区。这种情况下,时间片3结束后,此内存区的值变成了1100。时间片4结束后,此内存区的变成了900。正确的结果应该是1000,而不是900。可看出,异常发生的原因是“两个重叠”。
异常消除
如何消除并发访问同一数据可能带来的异常呢?之前提到过异常发生的两个必要前提:“时间重叠”与“空间重叠”。因此可从两个角度出发,设计消除异常的方案。
最容易想到的方案是,为每一个线程分配连续的足够的时间片。这种做法的确可以避免“时间重叠”这种情况的发生,进而消除异常。但设想一下,若某线程负责下载容量几个G的影片,一旦其获得CPU的使用权,那么接下来的几十分钟内,您不能做任何事情,只能等待......。
“时间重叠”这种现象的确可消除,但一旦消除,所有线程串行化执行,用户体验非常差,这种方案不好。接下来,我们试着从“空间重叠”这个角度出发提出方案。共享内存区域是实现线程间通信的一种方式,将“共享内存区域”消除掉,也不太合适。
现实中,是通过“锁”消除并发访问同一数据带来的异常。“锁”的相关话题本文不涉及,太大,几句话讲不明白,随后会有相关文章呈现。