怪奇物语

怪奇物语

首页 新随笔 联系 管理

异步互斥锁 MutexLock 用锁和不用锁的对比

MutextLock\Program.cs


using System;
using System.Threading.Tasks;

class Program
{
    static AsyncExecutionLock _lock = new();

    static async Task Main()
    {
        await NotUseLock();
        await UseLock();
    }

    private static async Task UseLock()
    {
        int counter = 0;
        var asyncLock = new AsyncExecutionLock();

        List<Task> tasks = new();
        for (int i = 0; i < 1000; i++)
        {
            tasks.Add(
                Task.Run(() =>
                {
                    // 👇👇👇👇👇👇👇👇👇
                    asyncLock.Execute(() =>
                    {
                        counter++;
                    });
                })
            );
        }
        await Task.WhenAll(tasks);

        Console.WriteLine($"最终结果(有锁):{counter}"); // 结果等于1000
    }

    private static async Task NotUseLock()
    {
        int counter = 0;
        List<Task> tasks = new();
        for (int i = 0; i < 1000; i++)
        {
            tasks.Add(
                Task.Run(() =>
                {
                    // 多个线程同时修改 counter,可能导致丢失更新
                    counter++;
                })
            );
        }
        await Task.WhenAll(tasks);
        Console.WriteLine($"最终结果(无锁):{counter}"); // 结果通常小于1000
    }
}

MutextLock\AsyncExecutionLock.cs


public class AsyncExecutionLock
{
    // 声明一个信号量,初始计数为1,最大计数为1,相当于一个“异步互斥锁”
    private readonly SemaphoreSlim _semaphore = new(1, 1);

    // 同步执行:获得锁后执行action,执行完毕后释放锁
    public void Execute(Action action)
    {
        _semaphore.Wait(); // 阻塞直到获得信号量

        try
        {
            action.Invoke(); // 执行传入的同步委托
        }
        finally
        {
            _semaphore.Release(); // 无论是否异常都释放信号量
        }
    }

    // 异步执行:获得锁后执行异步action,执行完毕后释放锁
    public async Task ExecuteAsync(Func<Task> action)
    {
        await _semaphore.WaitAsync(); // 异步等待获得信号量

        try
        {
            await action.Invoke(); // 执行传入的异步委托
        }
        finally
        {
            _semaphore.Release(); // 无论是否异常都释放信号量
        }
    }

    // 异步执行并返回结果:获得锁后执行异步action,返回结果,执行完毕后释放锁
    public async Task<TReturn> ExecuteAsync<TReturn>(Func<Task<TReturn>> action)
    {
        await _semaphore.WaitAsync(); // 异步等待获得信号量

        try
        {
            return await action.Invoke(); // 执行传入的异步委托并返回结果
        }
        finally
        {
            _semaphore.Release(); // 无论是否异常都释放信号量
        }
    }
}


MutextLock\MutextLock.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

posted on 2025-07-03 08:00  超级无敌美少男战士  阅读(17)  评论(0)    收藏  举报