跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C Sharp 线程同步
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:C#线程同步}} == 简介 == '''线程同步'''是C#并发编程中的核心概念,指在多线程环境下协调多个线程对共享资源的访问,以避免'''竞态条件'''(Race Condition)和'''数据不一致'''问题。当多个线程同时访问共享数据时,如果没有同步机制,可能导致不可预测的结果。 线程同步的主要目标: * 确保线程安全(Thread Safety) * 维护数据一致性 * 防止死锁(Deadlock)和活锁(Livelock) * 优化性能与资源利用率 == 同步问题示例 == 以下是一个典型的未同步代码示例,展示多个线程同时修改共享变量时的问题: <syntaxhighlight lang="csharp"> using System; using System.Threading; class UnsafeCounter { private int _count = 0; public void Increment() { _count++; // 非原子操作 } public int GetCount() => _count; } class Program { static void Main() { var counter = new UnsafeCounter(); Thread thread1 = new Thread(() => { for (int i = 0; i < 100000; i++) counter.Increment(); }); Thread thread2 = new Thread(() => { for (int i = 0; i < 100000; i++) counter.Increment(); }); thread1.Start(); thread2.Start(); thread1.Join(); thread2.Join(); Console.WriteLine($"Expected: 200000, Actual: {counter.GetCount()}"); // 输出可能小于200000(如:123456) } } </syntaxhighlight> '''问题分析''':<code>_count++</code> 实际上包含读取、修改、写入三个步骤,线程可能在这些步骤之间被中断。 == 同步机制 == === lock 语句 === 最基本的同步机制,使用'''监视器模式'''(Monitor): <syntaxhighlight lang="csharp"> private readonly object _lockObj = new object(); private int _sharedValue; void SafeIncrement() { lock (_lockObj) { _sharedValue++; } } </syntaxhighlight> '''特点''': * 确保代码块在任意时刻只有一个线程可以执行 * 锁对象应为<code>private readonly</code>引用类型 * 避免锁定<code>this</code>、<code>Type</code>对象或字符串 === Monitor 类 === <code>lock</code>语句的底层实现: <syntaxhighlight lang="csharp"> Monitor.Enter(_lockObj); try { // 临界区代码 } finally { Monitor.Exit(_lockObj); } </code> '''高级用法''': * <code>Monitor.TryEnter</code>:带超时的尝试获取锁 * <code>Monitor.Wait</code>/<code>Pulse</code>:实现线程间信号 === Mutex === 系统级别的跨进程同步: <syntaxhighlight lang="csharp"> using var mutex = new Mutex(false, "Global\\MyAppMutex"); try { if (mutex.WaitOne(TimeSpan.FromSeconds(1))) { // 访问共享资源 } } finally { mutex.ReleaseMutex(); } </syntaxhighlight> === Semaphore/SemaphoreSlim === 限制同时访问资源的线程数量: <syntaxhighlight lang="csharp"> // 允许最多3个线程同时访问 SemaphoreSlim semaphore = new SemaphoreSlim(3); async Task AccessResource() { await semaphore.WaitAsync(); try { // 使用资源 } finally { semaphore.Release(); } } </syntaxhighlight> === ReaderWriterLockSlim === 优化读写场景: <syntaxhighlight lang="csharp"> private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); void ReadData() { _rwLock.EnterReadLock(); try { /* 读取操作 */ } finally { _rwLock.ExitReadLock(); } } void WriteData() { _rwLock.EnterWriteLock(); try { /* 写入操作 */ } finally { _rwLock.ExitWriteLock(); } } </syntaxhighlight> === 原子操作 === 使用<code>Interlocked</code>类实现简单操作的原子性: <syntaxhighlight lang="csharp"> int value = 0; Interlocked.Increment(ref value); // 原子递增 Interlocked.CompareExchange(ref value, 10, 0); // 原子比较交换 </syntaxhighlight> == 同步模式比较 == <mermaid> flowchart TD A[需要同步?] -->|是| B[简单原子操作?] B -->|是| C[使用Interlocked] B -->|否| D[读写比例?] D -->|读多写少| E[ReaderWriterLockSlim] D -->|读写均衡| F[lock/Monitor] D -->|限制并发数| G[Semaphore] A -->|跨进程| H[Mutex] </mermaid> == 死锁预防 == 死锁的四个必要条件: 1. 互斥条件 2. 占有并等待 3. 非抢占条件 4. 循环等待 '''预防策略''': * 按固定顺序获取锁 * 使用<code>Monitor.TryEnter</code>设置超时 * 减少锁的作用范围 * 避免嵌套锁 == 性能考量 == 同步机制的性能影响(从快到慢): <math> \text{Interlocked} \ll \text{lock} \approx \text{Monitor} \ll \text{ReaderWriterLockSlim} \ll \text{Mutex} </math> == 实际案例 == '''场景''':多线程日志系统 * 要求:线程安全写入日志文件 * 挑战:高并发写入不丢失日志 * 解决方案: <syntaxhighlight lang="csharp"> class ThreadSafeLogger { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); private StreamWriter _writer; public ThreadSafeLogger(string filePath) { _writer = new StreamWriter(filePath, append: true); } public void Log(string message) { _lock.EnterWriteLock(); try { _writer.WriteLine($"{DateTime.UtcNow:O}: {message}"); _writer.Flush(); } finally { _lock.ExitWriteLock(); } } } </syntaxhighlight> == 最佳实践 == 1. 尽可能减少共享状态 2. 优先考虑不可变对象 3. 使用更高级的并发集合(如<code>ConcurrentQueue</code>) 4. 锁的范围应尽可能小 5. 避免在锁内调用外部代码 6. 考虑使用异步同步(如<code>SemaphoreSlim.WaitAsync</code>) == 进阶主题 == * 内存模型与<code>volatile</code>关键字 * 线程亲和性与同步上下文 * <code>SpinLock</code>在高竞争场景的应用 * 无锁编程模式 {{Note|警告|不当的同步可能导致性能下降甚至程序挂起。始终在真实负载下测试同步方案。}} [[Category:编程语言]] [[Category:C Sharp]] [[Category:C Sharp 并发与多线程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:Note
(
编辑
)