并发 并行 同步 异步 多线程 阻塞 非阻塞

前言

最近iOS开发群里兄弟们讨论网络层这块的东西比较多,问题主要集中在请求、线程、队列这几块。中途发现对并发、异步、多线程等这些概念有一定的误解,特写此篇文章以作阐释。

这篇文章就主要会讲这些方面:
  1. 几个概念的字面意义
  2. 几个概念的详细理解
  3. 总结

几个概念的字面意义

  1. 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

  2. 并行:一组程序按独立异步的速度执行,不等于时间上的重叠(同一个时刻发生)。

  3. 同步:指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。

  4. 异步:异步双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位。

  5. 多线程:是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。

  6. 阻塞:是指程序调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,CPU不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。

  7. 非阻塞:指在不能立刻得到函数运行结果之前,该函数不会阻塞当前线程,而会立刻返回。

几个概念的应用领域

以上几个概念的字面意思请大家看上三遍。然后按照字面意思来个配对。

  • [并发、并行]
  • [同步、异步]
  • [阻塞、非阻塞]
  • 多线程

并发

并发大家肯定平时经常提及,不管是app、web server并发无处不在。仔细看上面并发的字面意思,是指一个时间段内多个程序(任务)同时处于运行活动状态,而不是在某一个时间点上都处于运行状态。参与并发的程序(任务)都是串行执行的,所以不存在同时刻执行多个程序(任务)的情况。那问题来了,为什么咱们平时编码的过程中发现多个任务都是同时执行的呢?因为有系统时间片轮转的参与,操作系统通过将cpu的执行时间分割成多个时间片,为每个程序(任务)分配时间片,因为cpu处理速度很快,这样就有了看起来好像每个任务都在同时执行的宏观感受,感觉有多个cpu,但本质上一个时间点只有一个程序(任务)在运行。


con.png

并行

而相对并发,并行可能陌生了不少,或许咱们还会会当做同一个概念来理解。虽然并行有和并发相同的外部特征,但是内部实现是不一样的。而且并行的原理也比并发简单,笼统的说就是套物理硬件的堆砌来实现,通过增加cpu核心来实现多个程序(任务)的同时进行。是的,是并行做到了多任务的同时执行。

par.png

同步

在多个逻辑调用间有一定的时间关系,就好比拿出钥匙才能去开门。前一个逻辑调用的输出作为第二个逻辑调用的输入,后一个逻辑调用必须等待前一个调用执行完才能开始调起执行。这个很好理解。

异步

正好与同步相反,后一个逻辑调用无需等待前一个逻辑调用执行完毕。也就是说前一个逻辑调用发起后就直接返回了,并没有输出,而是在调用执行完成后通过状态、通知来通知调用者,或通过回调函数处理这个调用。


阻塞

是指调用输出之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞

指在不能立刻返回调用输出之前,该调用不会阻塞当前线程。


多线程

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。在我看来,线程就是程序(任务)的执行载体,多线程则是并发的具体逻辑实现。所以,多线程就是并发,这个观念是错误了,两个领域的东西,这个不难理解。


总结

此刻大家应该能区分并发和并行了吧。对于并发和并行理解停留在概念阶段就可以,具体系统层面如何实现,只需了解即可。比较形象的比喻就是单车道和多车道。除去并发和并行,其他几个概念都是我们平时编码过程中经常用到的。多线程刚才说了是并发的代码逻辑实现,同步和异步是指逻辑调用方式,而阻塞和非阻塞则主要强调逻辑调用当前的状态。有同学可能会问并发和同步、异步有什么关系吗?明确的说没有关系,完全是两个领域的东西。也有同学会认为异步就是多线程,仔细看上面的解释,相信一定能明白。在开发过程中完全可以把并发和并行两个概念抛到脑后,因为修改并发和并行是靠修改系统层面配置或者提升硬件来解决,对于应用开发者,无需关心。

好了,现在再去看AFNetworking的源码,你是不是能理解AFNetworking处理多个请求只用了一个线程,给我们的感觉却是多个请求同时处理的呢?

废话有点多,大家勿喷啊,不对的地方希望能够帮忙指正(包括行文方面的问题)。

推荐阅读更多精彩内容