这篇文章的想法最早是在 2024 年 11 月 26 日产生的,拖到现在终于有空写完。今天,我想和大家聊聊一个常见的主题:《同步方法和异步方法的区别》。不知道大家是否也有过这样的疑问,很多时候同步方法和异步方法看起来差不多,但又好像不完全一样。

为什么会有这样的错觉?

首先,在同一个方法内,异步方法使用了 await 后,表面上看,除了界面不卡之外,执行过程和同步方法几乎没有什么区别。于是我们会产生一种错觉:是不是异步方法和同步方法其实没什么不同呢?

/// <summary>
/// 同步方法
/// </summary>
public static void SynchronousMethod()
{
Console.WriteLine("处理数据开始");
// 模拟等待(2秒)
Thread.Sleep(2000);
Console.WriteLine("同步操作1 完成");
// 再等待(2秒)
Thread.Sleep(2000);
Console.WriteLine("同步操作2 完成");
Console.WriteLine("数据处理完成");
}

/// <summary>
/// 异步方法
/// </summary>
/// <returns></returns>
public static async Task AsynchronousMethod()
{
Console.WriteLine("处理数据开始");
// 模拟等待(2秒)
await Task.Delay(2000);
Console.WriteLine("异步操作1 完成");
// 再等待(2秒)
await Task.Delay(2000);
Console.WriteLine("异步操作2 完成");
Console.WriteLine("数据处理完成");
}

同步方法与异步方法的底层差异

尽管表面上看起来像是同步的,但异步方法在底层和同步方法有很大的不同。如果在主线程上使用异步方法没有 await 的话,它可以去做其他事情。而同步方法在执行过程中会阻塞当前线程,直到它完成所有操作后才能继续执行下去。

例子说明

public async Task ProcessDataAsync()
{
    Console.WriteLine("开始处理数据");

    // 异步任务启动,但没有 await,直接执行后续代码
    var task = LongRunningOperationAsync();

    Console.WriteLine("数据处理中");

    // 在没有等待的情况下直接执行
    Console.WriteLine("数据处理结束");
}

public async Task LongRunningOperationAsync()
{
    await Task.Delay(5000);  // 模拟长时间操作
    Console.WriteLine("长时间操作完成");
}

总结

通过这些例子,我们可以看到,同步方法和异步方法看似相似,但其背后的执行机制大不相同。异步方法的真正优势在于,它可以在等待操作时释放线程去做其他事情,这有助于提高系统的并发性,尤其在处理 I/O 密集型任务时非常有效。而同步方法则在执行时阻塞线程,适合那些计算密集型的任务,但在高并发情况下可能会带来性能瓶颈。

通过 await,我们可以在确保顺序执行的同时,最大限度地释放线程资源,从而提高程序的效率。

代码仓库:https://github.com/peijiehuang/SynchronousAndAsynchronousMethods

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *