C# 中的同步 异步 阻塞 非阻塞 并发 并行编程

在软件开发领域,效率和性能至关重要。为了实现这些目标,开发人员采用了各种技术和方法,包括同步、异步、阻塞、非阻塞、并发和并行编程。每种方法都有自己的历史、目的、优点、缺点和应用。让我们深入研究每个概念以获得全面的理解。

1.同步编程

  • **历史和演变:**自计算机编程诞生以来,同步编程一直是传统方法。在同步编程中,任务以顺序方式一个接一个地执行。
  • **需求:**同步编程直观易懂,简化了控制流程,适合任务相互依赖完成的场景。
  • **缺点:**然而,当任务独立且可以并发执行时,同步编程会导致效率低下。它还可能导致阻塞,即一个任务阻碍其他任务的执行。
  • **最新版本:**尽管同步编程仍然很流行,但现代应用程序通常需要更有效的方法来处理复杂的任务。

示例 C# 代码

using System;

class Program
{
    /// <summary>
    /// 这是一个展示同步编程示例的程序
    /// Main 方法调用 Task1 和 Task2 方法来顺序执行任务
    /// </summary>
    static void Main(string[] args)
    {
        // 打印同步编程示例的消息
        Console.WriteLine("Synchronous Programming Example");

        // 调用 Task1 方法
        Task1();

        // 调用 Task2 方法
        Task2();
    }

    /// <summary>
    /// Task1 方法,模拟执行一个任务
    /// </summary>
    static void Task1()
    {
        // 打印执行任务1的消息
        Console.WriteLine("Executing Task 1...");

        // 任务1的逻辑(此处可以添加实际任务逻辑)
        
        // 打印任务1完成的消息
        Console.WriteLine("Task 1 Completed.");
    }

    /// <summary>
    /// Task2 方法,模拟执行另一个任务
    /// </summary>
    static void Task2()
    {
        // 打印执行任务2的消息
        Console.WriteLine("Executing Task 2...");

        // 任务2的逻辑(此处可以添加实际任务逻辑)
        
        // 打印任务2完成的消息
        Console.WriteLine("Task 2 Completed.");
    }
}

2.异步编程

  • **历史和演变:**随着软件系统变得越来越复杂,对异步编程的需求也随之出现。在异步编程中,任务独立于主程序流程执行,从而实现更好的资源利用率和响应能力。
  • **需求:**异步编程对于处理 I/O 绑定操作(例如网络请求或文件操作)至关重要,等待结果会浪费宝贵的 CPU 周期。
  • **缺点:**异步编程带来了复杂性,尤其是在管理共享资源或处理错误时。它需要对callbacks, promises或 async/await 结构有深入的了解。
  • **最新版本:**现代编程语言和框架为异步编程提供了强大的支持,具有 C# 中的 async/await 等功能。

示例 C# 代码

using System;
using System.Threading.Tasks;

class Program
{
    /// <summary>
    /// 这是一个展示异步编程示例的程序
    /// Main 方法调用 Task1Async 和 Task2Async 方法来异步执行任务
    /// </summary>
    static async Task Main(string[] args)
    {
        // 打印异步编程示例的消息
        Console.WriteLine("Asynchronous Programming Example");

        // 异步调用 Task1Async 方法并等待其完成
        await Task1Async();

        // 异步调用 Task2Async 方法并等待其完成
        await Task2Async();
    }

    /// <summary>
    /// Task1Async 方法,模拟异步执行一个任务
    /// </summary>
    static async Task Task1Async()
    {
        // 打印执行任务1的消息
        Console.WriteLine("Executing Task 1...");

        // 模拟异步操作,延迟2秒
        await Task.Delay(2000);

        // 打印任务1完成的消息
        Console.WriteLine("Task 1 Completed.");
    }

    /// <summary>
    /// Task2Async 方法,模拟异步执行另一个任务
    /// </summary>
    static async Task Task2Async()
    {
        // 打印执行任务2的消息
        Console.WriteLine("Executing Task 2...");

        // 模拟异步操作,延迟3秒
        await Task.Delay(3000);

        // 打印任务2完成的消息
        Console.WriteLine("Task 2 Completed.");
    }
}

3. 阻塞与非阻塞

  • **阻塞:**在阻塞操作中,任务会等待其完成,然后才允许其他任务继续执行。这可能会导致效率低下,尤其是在长时间运行操作的情况下。
  • **非阻塞:**另一方面,非阻塞操作允许任务继续执行,即使请求的操作尚未完成。这提高了资源利用率和响应能力。

示例 C# 代码

using System;
using System.Threading.Tasks;

class Program
{
    /// <summary>
    /// 这是一个展示阻塞和非阻塞操作的异步编程示例
    /// Main 方法调用 BlockingOperation 和 NonBlockingOperation 方法来演示两种操作
    /// </summary>
    static async Task Main(string[] args)
    {
        // 阻塞操作
        Console.WriteLine("Starting blocking operation...");
        await BlockingOperation();
        Console.WriteLine("Blocking operation completed.");

        // 非阻塞操作
        Console.WriteLine("Starting non-blocking operation...");
        Task nonBlockingTask = NonBlockingOperation();
        // 在非阻塞操作执行时做其他工作
        Console.WriteLine("Doing other work while non-blocking operation is in progress...");
        await nonBlockingTask;
        Console.WriteLine("Non-blocking operation completed.");

        // 提示用户按任意键退出
        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }

    /// <summary>
    /// BlockingOperation 方法,模拟一个耗时的阻塞操作
    /// </summary>
    static async Task BlockingOperation()
    {
        // 模拟一个耗时的阻塞操作,延迟3秒
        await Task.Delay(3000); // 3秒延迟
        Console.WriteLine("Blocking operation finished.");
    }

    /// <summary>
    /// NonBlockingOperation 方法,模拟一个耗时的非阻塞操作
    /// </summary>
    static async Task NonBlockingOperation()
    {
        // 模拟一个耗时的非阻塞操作,延迟2秒
        await Task.Delay(2000); // 2秒延迟
        Console.WriteLine("Non-blocking operation finished.");
    }
}

解释

  • **BlockingOperation:**表示需要 3 秒才能完成的阻塞操作。它被标记为异步以允许使用 await。
  • **NonBlockingOperation:**这表示需要 2 秒才能完成的非阻塞操作。它也被标记为异步。
  • 在 Main 方法中,阻塞操作用 await BlockingOperation() 调用,这意味着程序的执行将等到 BlockingOperation 完成。
  • 是,对于非阻塞操作,NonBlockingOperation 的调用无需等待,随后立即执行其他工作,从而允许程序在非阻塞操作进行时继续执行。

4.并发编程

  • **历史和演变:**并发编程使多个任务能够同时执行,从而有可能加快总体执行时间。
  • **需求:**随着多核处理器的出现,并发编程对于充分利用可用硬件资源变得至关重要。
  • **缺点:**并发编程引入了竞争条件和死锁等挑战,需要谨慎的同步机制来缓解。
  • **最新版本:**现代编程语言通过库、语言结构和框架提供强大的并发支持。

示例 C# 代码

using System;
using System.Threading.Tasks;

class Program
{
    /// <summary>
    /// 这是一个展示并发编程示例的程序
    /// Main 方法同时调用 Task1Async 和 Task2Async 方法,并等待它们都完成
    /// </summary>
    static async Task Main(string[] args)
    {
        // 打印并发编程示例的消息
        Console.WriteLine("Concurrent Programming Example");

        // 同时开始 Task1Async 和 Task2Async 方法
        Task task1 = Task1Async();
        Task task2 = Task2Async();

        // 等待所有任务完成
        await Task.WhenAll(task1, task2);

        // 打印所有任务完成的消息
        Console.WriteLine("Both tasks completed.");
    }

    /// <summary>
    /// Task1Async 方法,模拟异步执行一个任务
    /// </summary>
    static async Task Task1Async()
    {
        // 打印执行任务1的消息
        Console.WriteLine("Executing Task 1...");

        // 模拟异步操作,延迟2秒
        await Task.Delay(2000);

        // 打印任务1完成的消息
        Console.WriteLine("Task 1 Completed.");
    }

    /// <summary>
    /// Task2Async 方法,模拟异步执行另一个任务
    /// </summary>
    static async Task Task2Async()
    {
        // 打印执行任务2的消息
        Console.WriteLine("Executing Task 2...");

        // 模拟异步操作,延迟3秒
        await Task.Delay(3000);

        // 打印任务2完成的消息
        Console.WriteLine("Task 2 Completed.");
    }
}

5.并行编程

  • **历史和演变:**并行编程利用多核处理器并发执行任务,进一步提高性能。
  • **需求:**并行编程对于可分为独立子任务的计算密集型任务至关重要。
  • **缺点:**并行编程会因任务分配和同步而引入开销,并且需要仔细考虑负载平衡。
  • **最新版本:**现代并行编程框架和库提供高级抽象和自动并行化以简化开发。

示例 C# 代码

using System;
using System.Threading.Tasks;

class Program
{
    /// <summary>
    /// 这是一个展示并行编程示例的程序
    /// Main 方法使用 Parallel.Invoke 同时调用 Task1 和 Task2 方法
    /// </summary>
    static void Main(string[] args)
    {
        // 打印并行编程示例的消息
        Console.WriteLine("Parallel Programming Example");

        // 使用 Parallel.Invoke 同时执行 Task1 和 Task2 方法
        Parallel.Invoke(Task1, Task2);

        // 打印所有任务完成的消息
        Console.WriteLine("Both tasks completed.");
    }

    /// <summary>
    /// Task1 方法,模拟执行一个任务
    /// </summary>
    static void Task1()
    {
        // 打印执行任务1的消息
        Console.WriteLine("Executing Task 1...");

        // 任务1的逻辑(此处可以添加实际任务逻辑)

        // 打印任务1完成的消息
        Console.WriteLine("Task 1 Completed.");
    }

    /// <summary>
    /// Task2 方法,模拟执行另一个任务
    /// </summary>
    static void Task2()
    {
        // 打印执行任务2的消息
        Console.WriteLine("Executing Task 2...");

        // 任务2的逻辑(此处可以添加实际任务逻辑)

        // 打印任务2完成的消息
        Console.WriteLine("Task 2 Completed.");
    }
}

结论

理解并有效利用同步、异步、阻塞、非阻塞、并发和并行编程范式对于现代软件开发至关重要。每种方法都有自己的优点和缺点,选择合适的方法取决于应用程序的特定要求和约束。通过利用这些技术的正确组合,开发人员可以创建高性能、可扩展且响应迅速的软件解决方案来解决现代代码问题。

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谢.锋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值