文章目录
前言
我们可以通过使用不同的并发模型来实现一个并发系统,线程之间通过协作完成系统给定的任务。不同的并发模型以不同的方式切割任务,线程之间可能存在通信和合作完成不同的任务。
一、并发模型与分布式系统相似
- 在一个并发系统中,不同的线程之间相互通信。
- 在一个分布式系统中,不同的进程之间相互通信。
分布式系统比并发系统面临更多的挑战,比如可能面临网络异常、远程主机或进程停止;并发系统理论上也存在相似的问题,比如CPU异常,内存或硬盘损坏等情况,这种异常的概率相对较小,但实际上是存在的。
二、共享状态 vs 隔离状态
2.1 共享状态
共享状态意味着同一系统的多个线程之间共享一些状态(一般指数据,共享一个或多个对象的数据)。当线程共享状态时,容易引发一些并发问题,比如死锁,竞争条件等等,这取决于线程怎样地使用和访问共享数据等等。
2.2 隔离状态
隔离状态意味着同一系统的多个线程之间不共享状态。如果不同的线程之间需要进行通信,可以通过交换不可变对象、或者使用复制的对象进行通信。当多个线程之间不存在共享状态(或共享数据),就可以避免最常见的并发问题。
备注:隔离状态通常情况下可以让代码实现更加简单,并且可以不用担心发生并发访问的问题,避免一些常见的并发问题。在一些特殊情况下,使用分离状态并发设计可能存在更大的挑战。
三、并发模型
3.1 Parallel Workers (并行工作者并发模式)
并行工作者模式:
传入的工作被分配到不同的工作者去执行,每个工作者执行完整的工作流程。工作者在不同的线程中执行。并行工作者并发模型在 Java 应用程序中很常见,JUC包中很多并发工具类的设计都采用了这种并发模型。
优点:
- 非常容易理解:如果要提高并行效率只需要增加更多的工作者
缺点:
- 存在共享状态时实现更加复杂
- 工作顺序不固定
缺点1:存在共享状态时实现更加复杂
并行工作者模式不同线程存在共享数据时,实现变得更加复杂。共享线程通常需要访问共享对象,不论共享对象存在于内存中还是数据库中。如下图所示
某些共享状态是工作队列中的通信机制,也有些共享状态是业务数据、数据缓存、数据库连接池等等。
并行工作者并发模式的线程之间存在共享数据时会更加复杂,当一个线程修改了共享数据变量时,需要确保其他线程读取的共享数据变量是最新的(线程修改了共享数据变量应该把数据保存至主内存中,而不是保存至线程独有的CPU高速缓存栈中)。线程需要避免死锁、竞争条件、或者其他共享状态的并发问题。
当某个线程正在访问共享数据结构时,其他线程会等待正在访问共享数据结构的线程执行完毕,造成阻塞。这可能导致这些线程在竞争共享数据资源,高的竞争条件会导致许多线程访问共享数据时串行执行。
现代非阻塞并发算法可能降低竞争并且提高性能,但是非阻塞并发算法很难实现。
持久性数据结构是另一种选择,当持久性数据结构被修改时,他总是保持修改前版本。当多个线程引用了某个持久性数据结构,其中某个线程对持久性数据结构做了修改时,这个修改了持久性数据结构的线程获得了最新的引用数据,而其他的线程保持原来的引用的数据。在共享数据被修改时,持久性数据结构的方式是一个很好的解决方案。
关于持久性数据结构的举例:
- 当某个线程给ArrayList添加一个元素时,新添加的元素对其他线程并不可见
- 也存在某些缺陷,比如LinkedList, 由于LinkedList是链表的数据结构,链表的每个元素都是一个单独的对象,这种数据结构分布在内存块中的各个地方。然而现代CPU在访问顺序的数据结构时要快的多,比如ArrayList,所以CPU在访问ArrayList时能够表现出更加卓越的性能。CPU能够一次加载一个较大的数组类型的数据结构至高速缓存中,但是无法将一个元素分布至内存各个地方的链表(ListedList)加载到CPU的高速缓存中。
无状态工作者
共享数据可以被系统中某个线程修改,其他线程在每次访问共享数据时必须重新读取最新的内存中的数据,以保证线程在执行中时拿到的是最新的内存副本,一个线程不始终保持自己线程独有的CPU高速缓存数据的状态称为无状态。
缺点2:工作顺序不固定
工作A可能被分配给线程A执行,也可能被分配给线程B执行,因此并行工作者模式的执行顺序不是固定的。
3.2 Assembly Line (流水线并发模式)
这种模式就像工厂中流水线的工人一样,每个工作者只负责整个生产车间的一部分工作,每个工作者负责的这部分工作完成之后会传递给下一个工作者。
每个工作者在自己的线程内执行,不存在共享状态,流水线并发模式也被称为无共享并发模式。
流水线并发模式经常在非阻塞IO (NIO) 被设计使用。当一个工作者开始IO操作,其他工作者不需要等待IO操作结束。IO操作很慢,所以等待IO操作完成会浪费大量CPU时间,当IO操作完成时,IO操作的结果会被传递给其他工作者。
关于NIO, 在IO操作确定工人之间的界限。如图
实际上,工作模式可能不只一条流水线,大多数系统可以设计多条流水线。
工作可能并定向到一个工作者进行并行处理。比如一个工作可能同时被分配到工作执行器和日志执行器中执行。
流水线并发模式也被称为反应系统或者事件响应系统。
优点:
- 不共享状态
- 可以顺序执行工作
缺点
- 作业的执行分散在各个工人
- 调试更加复杂