同步(Synchronous)和异步(Asynchronous)

什么是同步(Synchronous)?

1.1 同步的定义

1.2 同步的特点

1.3 同步的代码示例

1.4 类比案例

什么是异步(Asynchronous)?

2.1 异步的定义

2.2 异步的特点

2.3 异步的代码示例

2.4 类比案例 

 同步 vs 异步

什么时候用同步?什么时候用异步?

3.1 使用同步的场景

3.2 使用异步的场景

4. 实现原理

4.1 同步实现原理

4.1.1 操作系统层面

4.1.2 编程语言层面

4.2 异步实现原理

4.2.1 操作系统层面

4.2.2 编程语言层面

5. 总结


什么是同步(Synchronous)?

1.1 同步的定义

同步指的是任务按顺序执行,一个任务完成后,才能开始下一个任务。就像排队买奶茶,你必须等前面的人买完,才能轮到你。

在Java中,同步操作会阻塞当前线程,直到任务完成。也就是说,程序会“停下来”等待任务结束,然后再继续执行后面的代码。

1.2 同步的特点

  • 顺序执行:任务是一个接一个完成的。

  • 阻塞:当前线程会等待任务完成。

  • 简单直观:代码逻辑清晰,容易理解。

1.3 同步的代码示例

/**
 * 作者:十五001
 *
 */
public class SynchronousExample {
    public static void main(String[] args) {
        System.out.println("任务1开始");
        task1(); // 同步任务1
        System.out.println("任务1结束");

        System.out.println("任务2开始");
        task2(); // 同步任务2
        System.out.println("任务2结束");
    }

    public static void task1() {
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("任务1完成");
    }

    public static void task2() {
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("任务2完成");
    }
}

输出结果:

任务1开始
任务1完成
任务1结束
任务2开始
任务2完成
任务2结束

解释:

  • 任务1和任务2是按顺序执行的。

  • 任务1完成后,任务2才开始。

  • 主线程会等待每个任务完成。

1.4 类比案例

什么是异步(Asynchronous)?

2.1 异步的定义

异步指的是任务可以在后台执行,不会阻塞当前线程。就像点外卖,你下单后不用一直等在门口,可以去做其他事情,外卖到了会通知你。

在Java中,异步操作允许任务在后台运行,主线程可以继续执行其他任务,而不需要等待。

2.2 异步的特点

  • 非阻塞:当前线程不会被阻塞,可以继续执行其他任务。

  • 并行执行:多个任务可以同时进行。

  • 回调或通知:任务完成后,通常会通过回调、Future或CompletableFuture等方式通知主线程。

2.3 异步的代码示例

import java.util.concurrent.CompletableFuture;

/**
 * 作者:十五001
 *
 */
public class AsynchronousExample {
    public static void main(String[] args) {
        System.out.println("主线程开始");

        // 异步任务1
        CompletableFuture.runAsync(() -> {
            System.out.println("异步任务1开始");
            try {
                Thread.sleep(1000); // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务1完成");
        });

        // 异步任务2
        CompletableFuture.runAsync(() -> {
            System.out.println("异步任务2开始");
            try {
                Thread.sleep(1000); // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务2完成");
        });

        System.out.println("主线程结束");
    }
}

输出结果:

主线程开始
主线程结束
异步任务1开始
异步任务2开始
异步任务1完成
异步任务2完成

解释:

  • 主线程不会等待异步任务完成,而是直接继续执行。

  • 异步任务1和异步任务2是同时运行的。

  • 异步任务完成后,会打印出结果。

2.4 类比案例 

 同步 vs 异步

特性同步(Synchronous)异步(Asynchronous)
执行方式顺序执行,一个任务完成后才开始下一个并行执行,多个任务可以同时进行
阻塞性阻塞当前线程,直到任务完成非阻塞,当前线程可以继续执行其他任务
适用场景简单任务、顺序执行的任务耗时任务、并行处理的任务
代码复杂度简单直观较复杂,需要处理回调或Future
资源占用占用资源较少可能占用更多资源(如线程池)

什么时候用同步?什么时候用异步?

3.1 使用同步的场景

  • 任务简单,执行时间短。

  • 任务之间有依赖关系,必须按顺序执行。

  • 需要确保线程安全(如使用synchronized)。

3.2 使用异步的场景

  • 任务耗时较长(如网络请求、文件读写)。

  • 需要提高程序的响应速度(如GUI应用)。

  • 多个任务可以并行执行。


4. 实现原理

4.1 同步实现原理

4.1.1 操作系统层面
  • 线程阻塞机制:在多线程编程中,当一个线程需要等待某个操作完成时,操作系统会将该线程挂起(放入阻塞队列),使其放弃 CPU 资源。例如,当一个线程进行磁盘 I/O 操作时,由于磁盘读写速度相对 CPU 计算速度非常慢,线程会进入阻塞状态,直到 I/O 操作完成。操作系统会在操作完成后将线程从阻塞队列中取出,重新放入就绪队列,等待 CPU 调度执行。
  • 互斥锁和信号量:同步机制常用于保护共享资源,防止多个线程同时访问和修改导致数据不一致。互斥锁(如 Java 中的 synchronized 关键字或 ReentrantLock)和信号量是常用的同步原语。当一个线程获取到互斥锁或信号量时,其他线程必须等待该线程释放锁或信号量后才能继续访问共享资源。
4.1.2 编程语言层面
  • 方法调用:在编程语言中,同步操作通常通过方法调用实现。当调用一个同步方法时,调用者会等待该方法执行完毕并返回结果后,才会继续执行后续代码。

4.2 异步实现原理

4.2.1 操作系统层面
  • 事件驱动机制:操作系统通过事件驱动机制来实现异步操作。当一个异步操作(如网络请求、文件读写)发起时,操作系统会将该操作注册到事件队列中,并立即返回。当操作完成时,操作系统会产生一个事件通知,调用者可以通过监听这些事件来获取操作结果。例如,在 Linux 系统中,epoll 是一种高效的事件驱动 I/O 机制,用于处理大量的异步 I/O 事件。
  • 异步 I/O 接口:现代操作系统提供了异步 I/O 接口,允许应用程序在不阻塞线程的情况下进行 I/O 操作。例如,Windows 系统的 ReadFileEx 和 WriteFileEx 函数,以及 Linux 系统的 aio_read 和 aio_write 函数。这些接口会在 I/O 操作完成后通过回调函数或信号通知应用程序。
4.2.2 编程语言层面
  • 回调函数:回调函数是一种常见的异步编程方式。调用者在发起异步操作时,会传递一个回调函数给异步操作的执行者。当操作完成后,执行者会调用该回调函数,并将操作结果作为参数传递给回调函数。
  • Promise 和 Future:许多编程语言提供了 Promise 或 Future 机制来处理异步操作。Promise 或 Future 表示一个异步操作的结果,它可以处于未完成、已完成或已失败三种状态。调用者可以通过 then 方法注册回调函数,当异步操作完成时,回调函数会被执行。

5. 总结

  • 同步:就像排队,一个接一个,简单但可能会慢。

  • 异步:就像多线程处理,可以同时做多件事,效率高但复杂一些。

在实际开发中,我们需要根据任务的特点选择合适的模式。如果是简单的任务,同步就够了;如果是耗时任务,异步可以大大提高效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十五001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值