关于 C# lock的理解

本文深入探讨了C#中的lock机制,解释了其在多线程环境下如何防止多个线程同时访问同一资源,从而避免数据竞争和不一致的问题。通过实例说明了lock的基本用法及注意事项。

昨天同事看了我在项目中用线程下载unity资源的功能,对其中lock的用法不明白,问我是怎么回事。在这里我就将这个问题记录下。
       当我们使用线程的时候,各个线程同时运行,其间不相互依赖和等待。但是当不同的线程都需要访问某个资源的时候,就需要同步机制,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被一个线程操作,以确保每个操作都是有效。lock是C#中最常用的同步方式,格式为lock(lockObject){code} 。

lock(lockObject){code}实际上有三个意思:
       1. lockObject被lock了吗?没有则由我来lock,否则一直等待,直至lockObject被释放。
       2. lock以后在执行code的期间其他线程不能调用code,也不能使用lockObject。
       3. 执行完code之后释放lockObject,并且code可以被其他线程访问。

lock在使用时的注意点:1、lock的是引用类型的对象,string类型除外。2、lock推荐的做法是使用静态的、只读的、私有的对象。3、保证lock的对象在外部无法修改才有意义,如果lock的对象在外部改变了,对其他线程就会畅通无阻,失去了lock的意义。

private readonly object lockObject = new object();

lock (lockObject)
    {
       //code
    }

 

### C# 中 `lock` 关键字的用法和原理 #### 使用场景 当多个线程访问共享资源时,可能会引发数据竞争条件。为了防止这种情况的发生,在特定的操作期间阻止其他线程进入该区域是非常重要的。此时就可以利用 `lock` 来确保同一时间只有一个线程能执行某段代码。 简单易用:通过使用 `lock` 可以快速实现线程同步[^2]。这使得开发者能够在不需要深入了解复杂的并发控制理论的情况下轻松管理多线程程序中的资源共享问题。 #### 工作原理 `lock` 实际上是一个语法糖,它背后调用了 Monitor 类来完成实际的工作。具体来说: - 当一个线程尝试获取某个对象上的锁时,如果当前没有任何其它线程持有此锁,则允许其获得并继续运行; - 如果已经有另一个线程持有了相同的锁,则新来的请求会被阻塞直到前者的释放为止; - 锁定的对象应该是专用于锁定目的实例变量,最好是私有的或受保护成员,并且不会被外部随意更改状态,从而减少死锁的风险。 ```csharp private readonly object _syncRoot = new(); public void IncrementCounter() { lock (_syncRoot) { Counter++; } } ``` 在此示例中,定义了一个名为 `_syncRoot` 的专用对象作为锁标志。每次想要修改计数器之前都会先检查是否有别的线程正在对其进行更新;如果有则等待对方完成后才继续自己的操作流程。 #### 多线程下的同步机制 在 .NET 平台下提供了多种不同的工具和技术帮助开发人员解决多线程编程带来的挑战之一——即如何安全有效地协调各个独立工作的进程之间的交互行为。除了上述提到过的基于监视器模式设计而成的 `lock` 语句之外还有诸如 `Interlocked`, `Monitor`, `Mutex` 等等其他的解决方案可供选择[^3]。 对于简单的互斥需求而言,`lock` 是最常用也是最容易理解和使用的选项之一。然而随着应用场景复杂度增加以及性能要求提高,可能就需要考虑采用更高级别的抽象层面上所提供的功能特性了。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值