简单来讲讲C#中的锁
简单来讲讲C#中的锁在多线程编程中锁是一种用于控制多个线程对共享资源访问的机制。C#作为一门支持多线程的编程语言提供了多种锁的实现方式帮助开发者避免数据竞争、死锁等问题。本文将从基础概念讲起逐步深入到高级用法并通过完整代码示例让你轻松掌握C#中的锁。## 什么是锁为什么需要锁当多个线程同时访问共享数据如全局变量、文件、数据库连接等时可能会发生“竞争条件”Race Condition。例如两个线程同时向一个整数变量加1由于操作不是原子的最终结果可能比预期小。锁的作用就是确保同一时间内只有一个线程能访问被保护的代码段从而保证数据的一致性。锁的基本原理是当一个线程试图进入被锁保护的代码块时它必须先获得锁如果锁已被其他线程持有则该线程会等待直到锁被释放。## 基础锁lock语句C#中最简单的锁是lock语句。它基于Monitor类实现用于同步对共享资源的访问。### 示例1使用lock保护共享变量csharpusing System;using System.Threading;class Program{ // 共享资源一个计数器 private static int counter 0; // 锁对象必须是一个引用类型不能为null private static readonly object lockObject new object(); static void Main() { // 创建两个线程同时递增计数器 Thread t1 new Thread(IncrementCounter); Thread t2 new Thread(IncrementCounter); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($最终计数器值: {counter}); // 预期输出10000 } static void IncrementCounter() { for (int i 0; i 5000; i) { // 使用lock确保原子操作 lock (lockObject) { counter; } } }}代码说明-lockObject是一个专用对象用于锁定。它必须是引用类型如object且通常声明为static readonly以确保唯一性。- 在lock块内counter是原子化的不会被其他线程中断。- 如果没有lock两个线程同时执行counter可能导致结果小于10000。###lock的注意事项- 不要锁值类型如int因为它们会装箱导致每次锁的对象不同。- 不要锁字符串因为字符串可能被池化导致意外共享。- 锁的范围应尽可能小避免长时间持有锁。## 进阶用法Monitor类lock语句是Monitor类的简化语法。Monitor提供了更灵活的锁控制例如超时和手动等待。### 示例2使用Monitor实现超时锁csharpusing System;using System.Threading;class Program{ private static readonly object lockObject new object(); private static int sharedData 0; static void Main() { Thread t1 new Thread(TryEnterLock); Thread t2 new Thread(TryEnterLock); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($最终sharedData: {sharedData}); } static void TryEnterLock() { bool lockTaken false; try { // 尝试在1秒内获取锁如果超时则放弃 Monitor.TryEnter(lockObject, TimeSpan.FromSeconds(1), ref lockTaken); if (lockTaken) { Console.WriteLine(${Thread.CurrentThread.ManagedThreadId} 获得了锁); // 模拟耗时操作 Thread.Sleep(500); sharedData; Console.WriteLine(${Thread.CurrentThread.ManagedThreadId} 完成了操作); } else { Console.WriteLine(${Thread.CurrentThread.ManagedThreadId} 获取锁超时); } } finally { if (lockTaken) { Monitor.Exit(lockObject); } } }}代码说明-Monitor.TryEnter允许设置超时时间避免线程无限等待。- 使用try-finally确保锁总是被释放即使发生异常。- 此例中一个线程获得锁后睡眠500毫秒另一个线程尝试获取锁但超时因为总超时1秒而锁持有时间500毫秒实际可能成功但设计上展示了超时机制。## 高级用法ReaderWriterLockSlim当读操作远多于写操作时使用lock会导致所有读取线程互相阻塞影响性能。ReaderWriterLockSlim允许多个线程同时读取但写操作独占。### 示例3使用ReaderWriterLockSlim优化读写csharpusing System;using System.Threading;class Program{ private static readonly ReaderWriterLockSlim rwLock new ReaderWriterLockSlim(); private static int sharedData 0; static void Main() { // 创建3个读线程和2个写线程 for (int i 0; i 3; i) { int threadId i; new Thread(() Reader(threadId)).Start(); } for (int i 0; i 2; i) { int threadId i; new Thread(() Writer(threadId)).Start(); } Thread.Sleep(2000); // 等待线程执行 } static void Reader(int id) { rwLock.EnterReadLock(); try { Console.WriteLine($读取线程{id} 读取到值: {sharedData}); Thread.Sleep(100); // 模拟读取耗时 } finally { rwLock.ExitReadLock(); } } static void Writer(int id) { rwLock.EnterWriteLock(); try { sharedData; Console.WriteLine($写入线程{id} 写入新值: {sharedData}); Thread.Sleep(200); // 模拟写入耗时 } finally { rwLock.ExitWriteLock(); } }}代码说明- 多个读线程可以同时进入读锁不会互相阻塞。- 写线程需要独占写锁此时所有读线程和其他写线程都会等待。- 这种锁适用于缓存、配置等读多写少的场景。## 高级用法SpinLockSpinLock是一种轻量级锁适用于锁持有时间极短的场景。它不会让线程进入休眠即不进行上下文切换而是让线程自旋等待从而减少开销。### 示例4使用SpinLockcsharpusing System;using System.Threading;class Program{ private static SpinLock spinLock new SpinLock(); private static int counter 0; static void Main() { Thread t1 new Thread(Increment); Thread t2 new Thread(Increment); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($最终counter: {counter}); } static void Increment() { bool lockTaken false; for (int i 0; i 10000; i) { try { spinLock.Enter(ref lockTaken); counter; } finally { if (lockTaken) spinLock.Exit(); lockTaken false; } } }}**代码说明**-SpinLock需要显式调用Enter和Exit且必须传递ref bool参数。- 由于自旋会占用CPU时间不适合长时间等待的场景如I/O操作。- 在.NET Core/.NET 5中SpinLock性能较好但需谨慎使用。## 总结C#中的锁是多线程编程的核心工具。从简单的lock语句到高级的ReaderWriterLockSlim和SpinLock每种锁都有其适用场景- **lock**最常用适合大多数同步需求语法简洁。- **Monitor**提供超时等高级控制适合需要避免死锁的场景。- **ReaderWriterLockSlim**读多写少场景下的性能优化。- **SpinLock**极短等待时间下的轻量级方案。使用锁时务必遵循“最小化锁范围”原则避免死锁如多个锁嵌套时注意顺序并优先考虑更高级的同步原语如ConcurrentDictionary、SemaphoreSlim 等。掌握这些锁的用法你就能在C#中构建稳定高效的多线程程序了。

相关新闻

梯度下降与神经网络优化:从原理到实践

梯度下降与神经网络优化:从原理到实践

1. 从梯度下降到神经网络学习的核心脉络第一次接触机器学习时,我被"梯度下降"这个数学概念困扰了很久。直到亲手用Python实现了一个简单的线性回归,看着损失函数曲线随着迭代次数的增加逐渐下降,才真正理解了为什么这个优化算法会成…

2026/10/5 22:50:46 阅读更多 →
第二十三章 WSaiOS 感知学习与自适应进化机制实现

第二十三章 WSaiOS 感知学习与自适应进化机制实现

📂 《WSaiOS 人工智能感知篇》第二十三章WSaiOS 感知学习与自适应进化机制实现WSaiOS Perception Learning & Adaptive Evolution Mechanism——让人工认知系统从固定感知走向持续进化作者:东塬一老翁23.1 感知学习提出前面的章节建立了:…

2026/10/8 6:25:28 阅读更多 →
GPT-5.4 生成的单元测试你敢直接 commit?覆盖率85%背后的四重陷阱与Mock实战

GPT-5.4 生成的单元测试你敢直接 commit?覆盖率85%背后的四重陷阱与Mock实战

AI 生成单元测试的实战陷阱与突围之路——从 20% 到 85% 覆盖率的血泪史 上周,我们团队在 Taotoken 平台上调用 GPT-5.4 为遗留 Java 服务补全单元测试,覆盖率从可怜的 20% 一跃升至 85%。然而,还没来得及庆祝,CI 流水线就接连爆…

2026/10/13 3:06:05 阅读更多 →

最新新闻

哇塞!原来毕业论文还能这样写?2026降AIGC网站推荐合集

哇塞!原来毕业论文还能这样写?2026降AIGC网站推荐合集

一、核心工具 TOP4(实测有效) 1. 千笔AI—— 中文双降天花板(首选) 核心优势:查重 降 AI 双效合一,适配知网 / 维普 / 万方 2026 最新算法,实测重复率 42%→8.3%、AIGC 率 56%→4.2%。 核心功能…

2026/10/15 1:16:56 阅读更多 →
MIPS单周期CPU数据通路从零搭建:指令、硬件与控制信号全解析

MIPS单周期CPU数据通路从零搭建:指令、硬件与控制信号全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:16:56 阅读更多 →
交叉验证:原理、变体与规避评估陷阱的完整指南

交叉验证:原理、变体与规避评估陷阱的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:16:56 阅读更多 →
PyTorch工程化源码拆解:数据流、训练循环与部署落地

PyTorch工程化源码拆解:数据流、训练循环与部署落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:16:56 阅读更多 →
Python爬虫实战:requests+XPath稳定抓取豆瓣TOP250图书数据

Python爬虫实战:requests+XPath稳定抓取豆瓣TOP250图书数据

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:16:56 阅读更多 →
基于MP2642GR-Z与STM32F411RE的串联电池主动均衡器设计实践

基于MP2642GR-Z与STM32F411RE的串联电池主动均衡器设计实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:15:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →