C#多线程访问资源的实现示例

 更新时间:2026年01月09日 10:04:19   作者:Winemonk  
C#中多线程访问共享资源需要通过同步机制来保证线程安全,通过合理选择同步机制,可以平衡性能与线程安全,下面就来介绍一下如何实现,感兴趣的可以了解一下

在 C# 中,多线程访问共享资源需要通过同步机制来保证线程安全。以下是常见的解决方案及其适用场景:

1.1 锁机制

  1. lock 关键字

    • 基于 Monitor 类,确保代码块同一时间仅一个线程进入。
    • 适用场景:简单临界区保护。
    private readonly object _lockObj = new object();
    lock (_lockObj) 
    {
        // 访问共享资源
    }
    
  2. Monitor

    • 提供更灵活的控制(如超时机制)。
    Monitor.Enter(_lockObj);
    try { /* 操作资源 */ }
    finally { Monitor.Exit(_lockObj); }
    
  3. Mutex (互斥锁)

    • 跨进程同步,适用于多进程共享资源。
    using var mutex = new Mutex(false, "GlobalMutexName");
    mutex.WaitOne();
    try { /* 操作资源 */ }
    finally { mutex.ReleaseMutex(); }
    
  4. SpinLock (自旋锁)

    • 通过循环等待避免上下文切换,适用于极短临界区。
    SpinLock spinLock = new SpinLock();
    bool lockTaken = false;
    spinLock.Enter(ref lockTaken);
    try { /* 操作资源 */ }
    finally { if (lockTaken) spinLock.Exit(); }
    

1.2 信号量机制

  1. Semaphore / SemaphoreSlim

    • 控制同时访问资源的线程数量。
    SemaphoreSlim semaphore = new SemaphoreSlim(3); // 允许3个线程进入
    await semaphore.WaitAsync();
    try { /* 操作资源 */ }
    finally { semaphore.Release(); }
    
  2. ReaderWriterLockSlim

    • 读写分离锁,允许多读单写。
    ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
    rwLock.EnterReadLock();  // 读模式
    try { /* 读取资源 */ }
    finally { rwLock.ExitReadLock(); }
    
    rwLock.EnterWriteLock(); // 写模式
    try { /* 修改资源 */ }
    finally { rwLock.ExitWriteLock(); }
    

1.3 事件与信号

  1. ManualResetEvent / AutoResetEvent

    • 通过信号控制线程阻塞与唤醒。
    ManualResetEvent mre = new ManualResetEvent(false);
    mre.WaitOne();    // 等待信号
    mre.Set();        // 发送信号
    
  2. Barrier (屏障)

    • 同步多个线程到同一阶段。
    Barrier barrier = new Barrier(3); // 等待3个线程到达
    barrier.SignalAndWait();          // 每个线程调用此方法
    
  3. CountdownEvent

    • 等待指定数量的操作完成。
    CountdownEvent cde = new CountdownEvent(3);
    cde.Signal();  // 每个线程完成后调用
    cde.Wait();    // 等待所有完成
    

1.4 原子操作

  1. Interlocked

    • 提供原子操作(如递增、比较交换)。
    int value = 0;
    Interlocked.Increment(ref value); // 原子递增
    

1.5 线程安全集合

  1. ConcurrentQueue / ConcurrentDictionary

    • 内置线程安全的集合,避免手动同步。
    var queue = new ConcurrentQueue<int>();
    queue.Enqueue(1);
    if (queue.TryDequeue(out var item)) { /* 处理元素 */ }
    

1.6 避免共享状态

  1. 不可变对象

    • 使用 readonly 或不可变集合(如 ImmutableList),确保数据不可变。
    var list = ImmutableList.Create<int>();
    list = list.Add(1); // 返回新实例,原数据不变
    
  2. 线程本地存储

    • 使用 ThreadLocal<T>[ThreadStatic] 为每个线程创建独立副本。
    ThreadLocal<int> threadLocal = new ThreadLocal<int>(() => 0);
    int localValue = threadLocal.Value;
    

1.7 异步与并行

  1. async/await 与异步锁

    • 在异步代码中使用 SemaphoreSlim.WaitAsync()
    private SemaphoreSlim asyncLock = new SemaphoreSlim(1);
    await asyncLock.WaitAsync();
    try { /* 异步操作资源 */ }
    finally { asyncLock.Release(); }
    
  2. TPL (任务并行库)

    • 使用 Parallel.ForTask 时确保资源安全。
    Parallel.For(0, 10, i => 
    {
        // 需要内部同步机制
    });
    

1.8 选择策略

  • 简单临界区:优先使用 lockMonitor
  • 读写分离:使用 ReaderWriterLockSlim
  • 高并发读:不可变对象或并发集合。
  • 异步场景SemaphoreSlim.WaitAsync()
  • 跨进程同步Mutex

通过合理选择同步机制,可以平衡性能与线程安全。

到此这篇关于C#多线程访问资源的实现示例的文章就介绍到这了,更多相关C#多线程访问资源内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# FileStream实现大文件复制

    C# FileStream实现大文件复制

    这篇文章主要为大家详细介绍了C# FileStream实现大文件复制,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • c#入门之实现简易存款利息计算器示例

    c#入门之实现简易存款利息计算器示例

    这篇文章主要介绍了c#入门之实现简易存款利息计算器示例,需要的朋友可以参考下
    2014-04-04
  • C# 中 List 与 List 多层嵌套不改变原值的实现方法(深度复制)

    C# 中 List 与 List 多层嵌套不改变原值的实现方法(深度复制)

    这篇文章主要介绍了C# 中 List 与 List 多层嵌套不改变原值的实现方法,使用 BinaryFormatter 将原始 List 序列化为字节流,然后再反序列化得到新的 List,实现了深度复制,需要的朋友可以参考下
    2024-03-03
  • C#用表达式树构建动态查询的方法

    C#用表达式树构建动态查询的方法

    这篇文章主要介绍了C#用表达式树构建动态查询的方法,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下
    2020-12-12
  • C#实现语音播报功能

    C#实现语音播报功能

    这篇文章主要为大家详细介绍了C#实现语音播报功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C#中实现插入、删除Excel分页符的方法

    C#中实现插入、删除Excel分页符的方法

    这篇文章主要给大家介绍了关于在C#中实现插入、删除Excel分页符的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • C# 读写编辑INI文件的操作

    C# 读写编辑INI文件的操作

    INI就是扩展名为"INI"的文件,其实他本身是个文本文件,可以用记事本打开,主要存放的是用户所做的选择或系统的各种参数,这篇文章主要介绍了C#读写编辑INI文件的操作,需要的朋友可以参考下
    2023-05-05
  • C# DataSet结合FlyTreeView实现显示树状模型数据

    C# DataSet结合FlyTreeView实现显示树状模型数据

    NineRays.WebControls.FlyTreeView 是 9rays.net 推出的一款功能强大的树状模型数据显示控件,本文主要介绍了如何使用其并结合 DataSet对象进行数据显示,感兴趣的可以了解下
    2024-04-04
  • 一文带你了解C#操作MySql的方法

    一文带你了解C#操作MySql的方法

    工作中大多数情况下用的都是 MySql 但一直没有记录,相关操作。这篇文章以便 MySql.Data 库进行MySql操作,使用 C# 执行 SQL 语句,造个轮子
    2023-03-03
  • C#二分查找算法实例分析

    C#二分查找算法实例分析

    这篇文章主要介绍了C#二分查找算法,实例分析了C#二分查找的相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04

最新评论