[Java 并发编程] 3. 并发模型


前言

我们可以通过使用不同的并发模型来实现一个并发系统,线程之间通过协作完成系统给定的任务。不同的并发模型以不同的方式切割任务,线程之间可能存在通信和合作完成不同的任务。


一、并发模型与分布式系统相似

  • 在一个并发系统中,不同的线程之间相互通信。
  • 在一个分布式系统中,不同的进程之间相互通信。

分布式系统比并发系统面临更多的挑战,比如可能面临网络异常、远程主机或进程停止;并发系统理论上也存在相似的问题,比如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操作确定工人之间的界限。如图

在这里插入图片描述
实际上,工作模式可能不只一条流水线,大多数系统可以设计多条流水线。

工作可能并定向到一个工作者进行并行处理。比如一个工作可能同时被分配到工作执行器和日志执行器中执行。

流水线并发模式也被称为反应系统或者事件响应系统。

优点:

  • 不共享状态
  • 可以顺序执行工作

缺点

  • 作业的执行分散在各个工人
  • 调试更加复杂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值