架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 41596|回复: 4

[资料] .NET/C# Lock 锁原理 Monitor 深入讲解

[复制链接]
发表于 2021-4-29 09:54:10 | 显示全部楼层 |阅读模式
该lock语句获取给定对象的互斥锁,执行一个语句块,然后释放该锁。持有锁时,持有锁的线程可以再次获取并释放该锁。任何其他线程都被阻止获取该锁,并等待直到释放该锁。

回顾:

.net/c# 用户多线程并发lock(string){...}详解
https://www.itsvse.com/thread-7764-1-1.html

使用 lock 代码

等同于

可以认为 Lock 的底层代码就是 Monitor 实现的。

由于代码使用try ... finally块,因此即使在lock语句主体中引发异常,也会释放该锁。

您不能在语句主体中使用await运算符lock。您不能在语句主体中使用await运算符lock。您不能在语句主体中使用await运算符lock。您不能在语句主体中使用await运算符lock。这句话非常重要!

文档:超链接登录可见。

我自己测试代码,使用 Task 获取锁,并使用 await 阻塞,代码如下:

再多次执行如下代码后,执行结果不符合预期。

QQ截图20210429094919.jpg

为什么呢?如果试图在lock块中使用await关键字时使用lock关键字,会得到这个编译错误:cannot await in the body of a lock statement。原因是在await完成之后,该方法可能会在一个不同的线程中运行,而不是await关键字之前的线程(调用线程)。lock关键字需要同一个线程中获取锁和释放锁
修改代码,可以更直观的看到原因:

获取锁的线程Id和释放锁的线程Id,明显不在一个线程上面,所以造成无法成功释放锁,如下图:

QQ截图20210429095916.jpg

尝试修改代码,使用 thread 测试,执行多次,都符合预期,代码如下:

QQ截图20210429095142.jpg

(完)





上一篇:(转).NET/C# 将文件夹打包成 zip 文件
下一篇:Redis 使用 Lua 脚本详解
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2022-2-10 09:20:09 | 显示全部楼层
QQ截图20220210091725.jpg
不释放锁





码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2023-6-25 19:57:43 | 显示全部楼层
Object synchronization method was called from an unsynchronized block of code.
以下代码会报错如上




码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2023-8-12 19:47:49 | 显示全部楼层
lock 语法糖,如下图:


QQ截图20230812194652.jpg



码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2024-7-11 10:44:02 | 显示全部楼层
【转】C# 多线程并发下各种锁的性能
https://www.itsvse.com/thread-10561-1-1.html
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2025-6-15 20:35

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表