这篇文章的想法最早是在 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