C#高级:使用锁语法避免线程竞争资源

发布于:2025-08-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、场景

  • 多线程环境中访问共享资源时,比如写入文件、修改共享变量等,使用 SemaphoreSlim可以防止线程间的竞争条件和数据不一致问题。

二、异步写法

class Program
{
    // 创建一个 SemaphoreSlim 实例,最大并发数为 1,确保同一时间只有一个线程可以写入文件
    private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

    static async Task Main(string[] args)
    {
        // 创建并启动异步任务,模拟多线程写入
        var task1 = Task.Run(async() => 
        {
            for (int i = 0; i < 10; i++)
            {
                var res = $"线程1第{i}次写入";
                await WriteToFileAsync(res);
            }
        }
            
        );
        var task2 = Task.Run(async () => {
            for (int i = 0; i < 10; i++)
            {
                var res = $"线程2第{i}次写入";
                await WriteToFileAsync(res);
            }
        });

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

        Console.WriteLine("所有任务已完成");
    }

    // 异步向文件写入数据的方法
    static async Task WriteToFileAsync(string data)
    {
        // 使用 SemaphoreSlim 控制并发访问
        await semaphore.WaitAsync();//【A】
        try
        {
            using (StreamWriter writer = new StreamWriter("data.txt", true))
            {
                await writer.WriteLineAsync($"{DateTime.Now}: {data}");
                Console.WriteLine(data);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // 释放锁,允许其他线程访问
           semaphore.Release();//【B】
        }
    }
}

若注释掉代码行【A】和【B】,将会出现线程冲突问题,因此,必须使用锁机制(例如 lock、SemaphoreSlim 等)来确保文件在同一时刻只能由一个线程访问

三、同步写法

改一下异步的写法即可:

 1.去掉await async等关键字
 2.await semaphore.WaitAsync() => semaphore.Wait()