LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

简单来讲讲C#中的锁

freeflydom
2025年10月10日 10:15 本文热度 91

🔑 简单来讲讲C#中的锁

✨ 前言

今天来说说C#中的锁,锁在日常开发中还是很常用的,但是用的不得当,或者骚操作比较多那么就会导致死锁,从而导致系统崩溃。

📖 简述

🧩 通俗理解

  • 在现实生活里,就像一把门锁。
  • 如果一个人进了房间并把门反锁,别人就得在外面等他出来。
  • 等里面的人出来并开锁后,下一个人才能进去。

👉 编程里的“锁”也是一样的:
它保证同一时刻只有一个线程能进入临界区(共享资源的代码块),从而避免混乱。


⚙️ 技术定义

在 并发编程 中,锁(Lock)是一种同步机制,用来 控制多个线程对共享资源的并发访问

  • 没有锁时:多个线程可能同时修改同一个变量、文件、数据库记录 → 造成 数据竞争 (Race Condition)
  • 有了锁后:一个线程进入临界区时,其它线程必须等待 → 保证 数据一致性

🔒 锁的关键特性

  1. 互斥性
    • 一次只能有一个线程持有锁。
    • 其他线程必须等待。
  2. 可见性
    • 线程释放锁前的修改,对之后获取锁的线程是可见的。
  3. 可重入性(C# 的 lock 是可重入的)
    • 同一线程可以多次进入同一把锁,而不会死锁自己。

💡 举例

下面就举个例子讲讲什么情况下就需要用到锁。

int a = 0;
// 并行++ 
Parallel.For(0, 1000, _ => { 
    a++;
});
// 会发现 a 的值小于 1000,因为并行操作导致了线程之间的竞争。
Console.WriteLine(a);

正常情况下,a的值应该是等于1000的,但由于这里使用了Parallel.For,会导致多个线程对同一个值进行++操作,从而导致最终的结果没有1000次。

那么如何避免这种情况呢,可以使用锁去避免。

// 使用锁解决线程竞争问题
object obj = new object();
int b = 0;
Parallel.For(0, 1000, _ => { 
    lock (obj) {
        b++;
    }
});
// 现在 b 的值一定是 1000,因为锁确保了同一时间只有一个线程可以执行 b++ 操作。
Console.WriteLine(b);

这里使用了一个object类型作为锁对象,这也是常见的锁对象,不一定非得使用object类型,其他引用类型也行。

🖼️ 运行结果

🚀 .net9 新的锁对象

上面已经通过简单的例子了解到了什么是锁,已经怎么使用锁,那么在.net9中可以直接使用lock对象作为锁。

ℹ️ 在使用.net9创建项目时,如果使用object类型的锁,rider编辑器会提示使用Lock类型作为锁。

⏳ 老写法

public class Lock
{
    private readonly object _lock = new();
    public void Foo()
    {
        lock (_lock)
        {
            Thread.Sleep(3000);
            Console.WriteLine("In Foo");
        }
    }
}

⚡ 新写法

public class Deadlock
{
    private readonly Lock _lock = new();
    public void Foo()
    {
        lock (_lock)
        {
            Thread.Sleep(3000);
            Console.WriteLine("In Foo");
        }
    }
}

📊 比较

特性传统的 object + lock(obj)(Monitor-based)用 System.Threading.Lock + lock(newLock)
锁对象类型意图性任意引用类型,不专门为锁“设计”专门的锁类型,用意明确
编译器识别/处理用 Monitor.Enter/Exit; lock(object) 被编译器转换为 Monitor 操作如果 lock 的目标是 Lock 类型,编译器 special-case 使用 EnterScope()/Dispose() 的新方式
内部机制使用 Monitor、SyncBlocks、Thin locks 等,涉及 object header,可能有额外开销新语义可以减少某些 Monitor 的开销,scope 块式释放锁,可能在某些场景性能更优
性能在高并发且锁竞争严重的场景下性能可能成为瓶颈在同样场景下可有更好的性能(但具体提升依赖于运行情况和 contention)
可读性/安全性用 object,可能误用;不容易一眼看出这是锁对象用 Lock 类型,代码语义直接告诉你“这是用来加锁的”

📝 总结

锁是并发编程里的“双刃剑”。

  • 用得好 👉 能保证线程安全,避免数据错乱。
  • 用不好 👉 容易掉进性能陷阱,甚至导致死锁,拖垮整个系统。

在 .NET 9 之前,我们习惯用 object 作为锁对象,但语义模糊,容易被误用。

而新的 System.Threading.Lock 专门为锁而生,让代码更直观,也在某些场景下带来性能提升。

所以:

  • 写 demo、小项目 → 用 lock(object) 依旧没问题。
  • 写业务、追求可维护性和性能 → 建议上手 .NET 9 的 Lock,让代码更优雅、更安全。

转自https://www.cnblogs.com/ZYPLJ/p/19102575


该文章在 2025/10/10 10:15:46 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved