并行并发 - 1.并行并发、异步同步

  1. 并行性 parallelism
  2. 并发性 Concurrency
    1. 并发和并行 Relationship
    2. 控制流 Control flow
      1. 异步方法调用 Asynchronous method invocation
      2. 同步 Synchronization
  3. Q&A
    1. 异步一定需要创建一个新的线程吗?
  4. 扩展阅读 See Also
  5. 参考 References

并行性 parallelism

并行性(parallelism) 是指 同时做若干件事情。1 如下图所示,多个 CPU(central processing unit)或者 一个CPU内的多个 core,可以同时执行若干件事情:

image-20210717202716201

Oracle 的官方教程中,介绍到,并行计算(Parallel computing)是将一个问题,拆分成若干个子问题(每一个子问题在一个单独的 thread 中执行),同时解决这些子问题,然后合并其结果,并传递给下一个子问题。

如下例所示,使用 parallelStream 并行地运行着Streams。

1
2
3
4
5
6
double average = roster
    .parallelStream()
    .filter(p -> p.getGender() == Person.Sex.MALE)
    .mapToInt(Person::getAge)
    .average()
    .getAsDouble();

从上例,我们可以看得出,具有并行性(parallelism)的事情往往具有共同的特点。

并行性(parallelism)所指代的事情往往是:

  • 无状态机器(finite-state machine),没有所谓的状态。如:批处理、HTTP请求等等

  • 事情 之间没有任何关联。不存在 事情A 需要等待 事情B 完成。

并发性 Concurrency

并发性(Concurrency) 是指打算做若干件事情 1 ,但实际上只能一件一件地做。

image-20210717205740228

在计算机地世界,由于事情间可以快速切换(上下文切换),所以我们有一种错觉——同一时刻我们在做着若干件事情。由于一个 CPU(central processing unit)拥有若干个核(core),在一个时间点,一个核(core)只能做一件事情。

  • 由于操作系统可以上下文切换(Context switch),所以我们可以说,单核(single core)具有并发性。
  • 由于进程中的线程,以上下文切换(Context switch),我们可以说,进程具有并发性。
  • 如果线程中有若干个协程(或纤程),我们也可以说,线程具有并发性。

并发和并行 Relationship

严格意义上,如果多个 core 执行 并发任务 时,该任务也可以被称为 并行任务。但 并行任务不一定是并发任务,并行任务们之间如果没有产生交点,它们实质上就和 单个 CPU 的程序、单个 core 的主线程没有任何差异。因此,我们在讨论 并行 时,往往是着眼于 任务 霸占了多少个 core 、kernel thread。

而讨论 并发(Concurrency)时,着眼在 交点该怎么处理 以及相关的 CPU如何更高效地利用

另一个关于两者区别的例子如下

  • 如果一个主线程,开启了若干条子线程,他们之间没有任何交点,并结束,那么这若干条子线程之间就是并行
  • 如果主线程必须等待子线程的任务结束,才能继续执行下一步,那么主线程和子线程之间就是并发

控制流 Control flow

多控制流(Control flow)的处理方案包含:异步方法调用(Asynchronous method invocation)、同步(Synchronization)等。

异步方法调用 Asynchronous method invocation

异步(Asynchrony ):Flow-A 执行异步,启动了一个 Flow-B,Flow-B 还没执行完,仅仅返回某种标志(可能是 信号、引用),Flow-A 得到该标志并继续执行(没有被堵塞 Non-blocking)。

常见的异步有:

enter image description here

同步 Synchronization

同步(Synchronization)分为两种:执行同步(synchronous execution)、数据同步,这里就 执行同步 进行讨论。执行同步 实际要达到的效果是 action(如线程) 按照一定顺序进行执行。

根据顺序(优先级)可以分为:

  • 先来的,抢占到并执行(如:synchronized
    • 后来的,排队
    • 后来的,继续争抢
  • 自定义优先级

示例:

  • 汇合(join up)。如下图:主线程和子线程进行汇合。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
    		// do sth
        }
    });
      
    // 子线程与主线程进行汇合
    // 在汇合之前,
    thread1.join();
    

    enter image description here

Q&A

异步一定需要创建一个新的线程吗?

答:异步不一定需要创建新的线程。

Asynchronous vs Multithreading - Is there a difference? - StackOverflow 一贴中写到,并非所有的异步都需要 CPU 参加进去,只有 CPU 需要参加的操作才需要创建/利用 新的线程。

举例,AIO 不需要创建新的线程,AIO 是利用 OS 的底层机制进行实现。2

扩展阅读 See Also

参考 References


「并行并发」 系列文章
Part 1 -并行并发 - 1.并行并发、异步同步
Part 2 -并行并发 - 2.线程