并发和并行的基础知识

1. 并发(Concurrency)的例子

场景:单核计算机同时运行多个应用程序

假设你正在使用一台单核 CPU 的计算机,你同时打开了以下任务:

  • 任务 A:听音乐(音乐播放器)。
  • 任务 B:编写文档(Word 文档)。
  • 任务 C:下载文件(浏览器)。

虽然只有一个 CPU 核心,这些任务似乎在"同时"进行,但实际上计算机通过快速切换任务来实现并发:

如何实现并发?

  1. 任务切片

    • CPU 分配时间片(如 10 毫秒)给每个任务。
    • 时间片到期后,切换到另一个任务。
  2. 任务调度

    • 操作系统(如 Windows 或 Linux)通过调度器管理任务的执行顺序。
    • 任务的切换对用户透明,用户感知不到切换过程。

具体流程:

  • 时间片 1:CPU 执行任务 A(播放音乐)。
  • 时间片 2:CPU 切换到任务 B(处理文档)。
  • 时间片 3:CPU 切换到任务 C(下载文件)。
  • 重复上述步骤。

尽管 CPU 在某一时刻只能执行一个任务,但因为切换速度极快(毫秒级),你会感觉这些任务在同时运行。


代码模拟:单线程并发任务

以下示例模拟单核 CPU 的任务切换:

java 复制代码
public class ConcurrencyExample {
    public static void main(String[] args) {
        Runnable musicTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Playing music...");
                sleep(100);
            }
        };

        Runnable documentTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Editing document...");
                sleep(100);
            }
        };

        Runnable downloadTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Downloading file...");
                sleep(100);
            }
        };

        // 按顺序执行任务,模拟任务切换
        for (int i = 0; i < 5; i++) {
            musicTask.run();
            documentTask.run();
            downloadTask.run();
        }
    }

    private static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

Playing music...
Editing document...
Downloading file...
Playing music...
Editing document...
Downloading file...
...
  • 每个任务交替运行,给人感觉是"同时"执行的。
  • 本质上是通过快速切换来模拟并发。

2. 并行(Parallelism)的例子

场景:多核计算机同时运行多个任务

现在假设你使用一台四核 CPU的计算机,仍然执行以下任务:

  • 任务 A:听音乐(音乐播放器)。
  • 任务 B:编写文档(Word 文档)。
  • 任务 C:下载文件(浏览器)。
  • 任务 D:视频压缩(FFmpeg)。

在多核环境下,不同任务可以真正同时运行,每个任务分配到一个 CPU 核心:

如何实现并行?

  1. 多核 CPU 的任务分配

    • CPU 核心 1:执行任务 A(音乐播放器)。
    • CPU 核心 2:执行任务 B(文档编辑)。
    • CPU 核心 3:执行任务 C(文件下载)。
    • CPU 核心 4:执行任务 D(视频压缩)。
  2. 真正的同时运行

    • 多核系统中,每个核心可以独立处理任务。
    • 这些任务在物理上同时运行,不需要时间片轮转。

代码模拟:多线程并行任务

以下代码使用多线程模拟多核 CPU 的并行执行:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ParallelismExample {
    public static void main(String[] args) {
        // 创建一个线程池,模拟 4 核 CPU
        ExecutorService executor = Executors.newFixedThreadPool(4);

        // 定义四个任务
        executor.submit(() -> playMusic());
        executor.submit(() -> editDocument());
        executor.submit(() -> downloadFile());
        executor.submit(() -> compressVideo());

        executor.shutdown();
    }

    private static void playMusic() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Playing music...");
            sleep(100);
        }
    }

    private static void editDocument() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Editing document...");
            sleep(100);
        }
    }

    private static void downloadFile() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Downloading file...");
            sleep(100);
        }
    }

    private static void compressVideo() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Compressing video...");
            sleep(100);
        }
    }

    private static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果(顺序可能不同):

Playing music...
Editing document...
Downloading file...
Compressing video...
Playing music...
Editing document...
Downloading file...
Compressing video...
...
  • 每个任务分配到不同的线程,线程在多核 CPU 上真正同时运行。
  • 输出顺序可能不同,取决于操作系统和线程调度器的工作方式。

3. 并发与并行的结合

场景:并发和并行的混合使用

假设:

  • 你有 4 核 CPU。
  • 运行 8 个任务(任务 A 到 H)。

操作系统会结合并发并行来调度任务:

  1. 并行
    • 4 个任务同时运行在 4 核 CPU 上。
  2. 并发
    • 当某个任务阻塞时(如 I/O 操作),CPU 切换到其他任务继续执行。
示意图
时间线: 核心 1   | A |   | B |   | A |   | B |
          核心 2   | C |   | D |   | C |   | D |
          核心 3   | E |   | F |   | E |   | F |
          核心 4   | G |   | H |   | G |   | H |

4. 实际应用场景

场景 并发(Concurrency) 并行(Parallelism)
浏览器加载网页 同时处理多个请求(图片、视频、CSS 文件) 在多核 CPU 上并行渲染页面、解码视频和执行脚本。
视频播放 同时缓冲、解码和播放视频流(逻辑上的并发)。 使用 GPU 解码并渲染视频帧(物理上的并行)。
编译代码 同时编译多个模块(逻辑并发)。 使用多核 CPU 同时编译多个模块(物理并行)。
AI 训练 同时加载数据、更新参数(逻辑并发)。 使用 GPU 同时训练多个神经网络或并行处理不同的数据批次。
操作系统任务调度 多个任务共享 CPU 时间片,逻辑上的并发。 多核 CPU 上任务真正同时运行。

5. 总结

  • 并发: 通过任务切换,多个任务在同一时间段内交替运行,强调任务管理和逻辑上的"同时进行"。
  • 并行: 依赖多核或分布式系统,多个任务在物理上真正同时运行,强调性能和效率提升。
相关推荐
淡写青春2093 分钟前
计算机基础---进程间通信和线程间通信的方式
java·开发语言·数据结构
《源码好优多》6 分钟前
基于Java Springboot未央商城管理系统
java·开发语言·spring boot
^Lim11 分钟前
esp32 JTAG 串口 bootload升级
java·linux·网络
江-小北16 分钟前
Java基础面试题04:Iterator 和 ListIterator 的区别是什么?
java·开发语言
wmd1316430671219 分钟前
IDEA插件CamelCase,快速转变命名格式
java·ide·intellij-idea
小林熬夜学编程35 分钟前
【Linux系统编程】第五十弹---构建高效单例模式线程池、详解线程安全与可重入性、解析死锁与避免策略,以及STL与智能指针的线程安全性探究
linux·运维·服务器·c语言·c++·安全·单例模式
玖玖玖 柒染35 分钟前
windows下sqlplus连接到linux oracle不成功
linux·windows·oracle
LuckyTHP36 分钟前
CentOS 9 无法启动急救方法
linux·运维·centos
Bonne journée37 分钟前
centos和ubuntu有什么区别?
linux·ubuntu·centos
vvw&39 分钟前
如何在 Ubuntu 22.04 上安装带有 Nginx 的 ELK Stack
linux·运维·nginx·ubuntu·elk·elasticsearch·开源项目