概述
本文主要介绍和并发相关的基本概念以帮助理解并发。首先说明什么是并发(与并行对比),随后从图灵机角度理解并发在计算机中的表现。再然后介绍多线程如何承载并发,并且举了一个例子帮助理解多线程。最后简单说明并发的难点。
并发与并行
如果某个系统支持两个或者多个动作(Action)同时存在,那么这个系统就是一个并发系统。
如果某个系统支持两个或者多个动作(Action)同时执行,那么这个系统就是一个并行系统。
“并行”概念是“并发”概念的子集。
并发 与 图灵机
通过图灵机理解并发。图灵机就是依靠对状态的记录和改变来进行运算的。图灵机里的纸带和状态寄存器用来记录状态,而读写头用来访问和改变状态。想象一下一个并行的图灵机(多个有独立状态寄存器和不同速度的读写头加上一条共享的纸带)就不难理解在这个模型下并发带来的复杂度。
参考:对于卡内基梅隆大学计算机系删除基础课程中的面向对象编程课程,如何理解他们提到的「面向对象编程既是反模块化的又是反并行的」? - 知乎
并发的载体 - 线程
线程基本介绍
并发的本质决定了,其是不同的动作中的代码在交替执行。假如说同一程序中有2段代码,需要并发执行,那么操作系统应该如何处理呢?更确切的说是,操作系统如何管理,能够使得两段代码对于CPU以及其他资源进行合理的使用?
抽象为线程。线程是操作系统为方便管理不同的并发代码抽象出来的概念。在一个程序中(进程)的2段代码需要并发(交替使用CPU)执行,操作系统应该如何抽象,表示这两段代码相关的内容呢? 正如进程是运行时的程序(代码)一样。线程可以看做是细粒度的进程,也就是说线程也是运行时的程序,只不过线程依赖于其所在的进程。通过线程来控制一个程序中两个不同的处理流程(两段代码)。(想了解更多线程方面的理论知识,可以先理解操作系统中的进程)
PS: 可能这两个流程会有一些公共的资源,这在后面互斥访问时会进行相应的介绍。
举例理解多线程
接下来举一个生活中的例子,帮助理解多线程。假如说你这个人是一个程序(运行时的进程),今天你需要完成两个任务:(1)在操场上跑20公里;(2)做20道数学题。这两个任务你可以一个一个执行,也可以交替执行(类似于(1)(2)(1)…)。并发类似于后面一种情况,即交替执行。因为在现实生活中你不太可能一下跑20公里,否则效率可能比较低,交替执行能够充分利用你的体力以及精力。于是,当中午的时候,你可能在操场上跑了10公里,做数学题做了7道。这里,跑步以及做数学题可以看做两个线程,可以交替占用你的时间与精力,并且两个线程各自记录着你任务的完成状态。
另外,发现一篇关于java多线程的文章,较为通俗,如下:
Java中的多线程你只要看这一篇就够了
并发难吗?
并发相对串行程序而言还是比较难的。
在串行程序中,代码的执行路径是可预测的。只要通过某种有条不紊有逻辑的方法,总是可以找到其中的逻辑错误和其他的bug。
在并发算法和多线程编程中,你需要考虑同时又多个执行流程的情况,以及如何对这些执行流程进行协调以完成指定的计算任务。新问题是由于不确定性和异步性直接导致的。