简单来讲讲C#中的锁
<h1 id="-简单来讲讲c中的锁">🔑 简单来讲讲C#中的锁</h1><h2 id="-前言">✨ 前言</h2>
<p>今天来说说C#中的锁,锁在日常开发中还是很常用的,但是用的不得当,或者骚操作比较多那么就会导致死锁,从而导致系统崩溃。</p>
<p>后面我会出一系列文章,来讲讲C#里面的代码和技巧,通过不断的学习积累,以达到我的跳槽目标。</p>
<p>文章中有任何错误的地方都可以指出,博主也在不断的学习中~</p>
<h2 id="-简述">📖 简述</h2>
<p>下面问问<code>AI</code>来简单了解下什么是锁,<code>AI</code>分析还是挺详细的。</p>
<h3 id="-通俗理解">🧩 通俗理解</h3>
<ul>
<li>在现实生活里,<strong>锁</strong>就像一把门锁。</li>
<li>如果一个人进了房间并把门反锁,别人就得在外面等他出来。</li>
<li>等里面的人出来并开锁后,下一个人才能进去。</li>
</ul>
<p>👉 编程里的“锁”也是一样的:<br>
它保证<strong>同一时刻只有一个线程能进入临界区(共享资源的代码块)</strong>,从而避免混乱。</p>
<hr>
<h3 id="️-技术定义">⚙️ 技术定义</h3>
<p>在 <strong>并发编程</strong> 中,<strong>锁(Lock)</strong>是一种同步机制,用来 <strong>控制多个线程对共享资源的并发访问</strong>。</p>
<ul>
<li>没有锁时:多个线程可能同时修改同一个变量、文件、数据库记录 → 造成 <strong>数据竞争 (Race Condition)</strong>。</li>
<li>有了锁后:一个线程进入临界区时,其它线程必须等待 → 保证 <strong>数据一致性</strong>。</li>
</ul>
<h3 id="-锁的关键特性">🔒 锁的关键特性</h3>
<ol>
<li><strong>互斥性</strong>
<ul>
<li>一次只能有一个线程持有锁。</li>
<li>其他线程必须等待。</li>
</ul>
</li>
<li><strong>可见性</strong>
<ul>
<li>线程释放锁前的修改,对之后获取锁的线程是可见的。</li>
</ul>
</li>
<li><strong>可重入性(C# 的 lock 是可重入的)</strong>
<ul>
<li>同一线程可以多次进入同一把锁,而不会死锁自己。</li>
</ul>
</li>
</ol>
<h2 id="-举例">💡 举例</h2>
<p>下面就举个例子讲讲什么情况下就需要用到锁。</p>
<pre><code class="language-c#">int a = 0;
// 并行++
Parallel.For(0, 1000, _ => {
a++;
});
// 会发现 a 的值小于 1000,因为并行操作导致了线程之间的竞争。
Console.WriteLine(a);
</code></pre>
<p>正常情况下,a的值应该是等于<code>1000</code>的,但由于这里使用了<code>Parallel.For</code>,会导致多个线程对同一个值进行<code>++</code>操作,从而导致最终的结果没有1000次。</p>
<p>那么如何避免这种情况呢,可以使用锁去避免。</p>
<pre><code class="language-c#">// 使用锁解决线程竞争问题
object obj = new object();
int b = 0;
Parallel.For(0, 1000, _ => {
lock (obj) {
b++;
}
});
// 现在 b 的值一定是 1000,因为锁确保了同一时间只有一个线程可以执行 b++ 操作。
Console.WriteLine(b);
</code></pre>
<p>这里使用了一个<code>object</code>类型作为锁对象,这也是常见的锁对象,不一定非得使用object类型,其他引用类型也行。</p>
<h3 id="️-运行结果">🖼️ 运行结果</h3>
<p><img src="https://img2024.cnblogs.com/blog/3091176/202509/3091176-20250920162959269-751912822.png" alt="1" loading="lazy"></p>
<h2 id="-net9-新的锁对象">🚀 .net9 新的锁对象</h2>
<p>上面已经通过简单的例子了解到了什么是锁,已经怎么使用锁,那么在<code>.net9</code>中可以直接使用<code>lock</code>对象作为锁。</p>
<blockquote>
<p>ℹ️ 在使用<code>.net9</code>创建项目时,如果使用<code>object</code>类型的锁,<code>rider</code>编辑器会提示使用<code>Lock</code>类型作为锁。</p>
</blockquote>
<h3 id="-老写法">⏳ 老写法</h3>
<pre><code class="language-c#">public class Lock
{
private readonly object _lock = new();
public void Foo()
{
lock (_lock)
{
Thread.Sleep(3000);
Console.WriteLine("In Foo");
}
}
}
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3091176/202509/3091176-20250920163024532-1447890800.png" alt="2" loading="lazy"></p>
<h3 id="-新写法">⚡ 新写法</h3>
<pre><code class="language-c#">public class Deadlock
{
private readonly Lock _lock = new();
public void Foo()
{
lock (_lock)
{
Thread.Sleep(3000);
Console.WriteLine("In Foo");
}
}
}
</code></pre>
<h3 id="-比较">📊 比较</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>传统的 <code>object</code> + <code>lock(obj)</code>(Monitor-based)</th>
<th>用 <code>System.Threading.Lock</code> + <code>lock(newLock)</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>锁对象类型意图性</td>
<td>任意引用类型,不专门为锁“设计”</td>
<td>专门的锁类型,用意明确</td>
</tr>
<tr>
<td>编译器识别/处理</td>
<td>用 <code>Monitor.Enter/Exit</code>; <code>lock(object)</code> 被编译器转换为 Monitor 操作</td>
<td>如果 <code>lock</code> 的目标是 <code>Lock</code> 类型,编译器 special-case 使用 <code>EnterScope()/Dispose()</code> 的新方式</td>
</tr>
<tr>
<td>内部机制</td>
<td>使用 <code>Monitor</code>、SyncBlocks、Thin locks 等,涉及 object header,可能有额外开销</td>
<td>新语义可以减少某些 Monitor 的开销,scope 块式释放锁,可能在某些场景性能更优</td>
</tr>
<tr>
<td>性能</td>
<td>在高并发且锁竞争严重的场景下性能可能成为瓶颈</td>
<td>在同样场景下可有更好的性能(但具体提升依赖于运行情况和 contention)</td>
</tr>
<tr>
<td>可读性/安全性</td>
<td>用 <code>object</code>,可能误用;不容易一眼看出这是锁对象</td>
<td>用 <code>Lock</code> 类型,代码语义直接告诉你“这是用来加锁的”</td>
</tr>
</tbody>
</table>
<h2 id="-总结">📝 总结</h2>
<p>锁是并发编程里的“双刃剑”。</p>
<ul>
<li><strong>用得好</strong> 👉 能保证线程安全,避免数据错乱。</li>
<li><strong>用不好</strong> 👉 容易掉进性能陷阱,甚至导致死锁,拖垮整个系统。</li>
</ul>
<p>在 .NET 9 之前,我们习惯用 <code>object</code> 作为锁对象,但语义模糊,容易被误用。</p>
<p>而新的 <code>System.Threading.Lock</code> 专门为锁而生,让代码更直观,也在某些场景下带来性能提升。</p>
<p>所以:</p>
<ul>
<li><strong>写 demo、小项目</strong> → 用 <code>lock(object)</code> 依旧没问题。</li>
<li><strong>写业务、追求可维护性和性能</strong> → 建议上手 .NET 9 的 <code>Lock</code>,让代码更优雅、更安全。</li>
</ul>
<p>👉 学会合理使用锁,能让你的程序更加稳定,也能减少“背锅”的机会。</p>
<h2 id="-相关链接">🔗 相关链接</h2>
<ul>
<li>【.NET 9新增的锁对象(Lock)是怎么一回事?】 https://www.bilibili.com/video/BV1rLp2zMEua/?share_source=copy_web&vd_source=fce337a51d11a67781404c67ec0b5084</li>
</ul><br><br>
来源:https://www.cnblogs.com/ZYPLJ/p/19102575
頁:
[1]