简单聊聊C#中lock关键字

为了避免多个线程同时操作同一资源,引起数据错误,通常我们会将这个资源加上锁,这样在同一时间只能有一个线程操作资源。在C#中我们使用lock关键字来锁定资源,那lock关键字是如何实现锁定的呢?

我们先看一段代码,非常简单的单例,相信你闭着眼睛也能写出来。代码如下:

上面的代码我就懒得解释了。我们重点关注lock(locker)这行,就是这行限制了多个线程对大括号内代码的同时访问。下面我们就来讲一个原理。不过讲原理之前,还得和大家确认一个知识点,其实lock只是语法糖,其实现其实是Monitor类,所以上面的代码和下面的代码是相等。代码如下:

没有异议的话,我们接着讲。我们还是看lock(locker)这一行,简单地想一想,lock关键字把locker对象锁住了,别的线程就进不来了,那它是怎么锁的呢?是在对象上打了什么标记吗?是把线程ID打到标记吗?我们先看一下堆中locker的对象结构。如下图:

对象在堆中除了数据区以外,还有两片区域:MethodTableRef、SyncBlockValue。其中MethodTableRef是指向MethodTable中这个类型(Type)定义,简单说就是这个对象是什么class定义的,这个不是我们今天讨论的重点,就过了。

我们重点看一下SyncBlockValue,这个值为DWORD类型,占用4个字节,也就是32位。这个值主要用来表示对象的不同功能,具体什么功能,要看这个32位如何赋值。一般将32位分为两段,前6位用以表示不同的功能,后26位用以表示对象的hash值、或者是SyncBlock的索引值。如下图:

回到lock(locker)这个主题上。其实你也应该猜到,如果想实现lock(locker),只要在locker的前六位功能位上设置一个标识位,标识这个对象已经被锁住就行。但具体被哪个线程锁住要记在哪边呢?这时就要用到后面26位了。这时后26位会指向g_pSyncTable的某一项。g_pSyncTable是CLR维护的一个包SyncBlock项的全局数组。这时的结构如下图:

我们结合上图再来回顾一下整个流程:比如有两个线程:线程A、线程B。线程A执行到lock(locker)这一行时,会先检查locker的6个功能位中有没有没锁住标识位(假如第五位表示锁),如果没有锁,则将第五位标为1(不一定是1,这里只是举例),然后到g_pSyncTable数组中申请一个SyncBlock,将当前线程ID等信息记录在里面,然后将这个SyncBlock的地址赋予locker对象的后26位值,这样资源就被线程A锁住了。这时线程B也执行到lock(locker)这一行,它检查前第五位,发现被锁住了,就会到SyncBlock检查锁住的线程ID是否和自己一致,不一致的话,它就会一直等待,直到线程A释放锁。

以上只是粗略地讲述一下锁的底层原理,可能有很多描述不准确的地方,比如哪个功能位表示锁,其实我也不太清楚,但大概原理应该没错。

最后留个问题:如果锁住的对象同时又想获取HashCode,该如何存储并得到呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea如何导入java工程_Eclipse java web项目 ,导入IntelliJ IDEA 完整操作!

或许你用惯了Eclipse,有点排斥其他工具了,你写框架的时候,编译速度是不是特别慢啊?有时候还超过45秒,自动取消运行!有时候代码是正常的,却无端端报错?下午吃个饭回来又好了&#xff…

行业思考 | 互联网对传统行业的降维打击

【行业思考】| 作者 / Edison Zhou这是EdisonTalk的第301篇原创内容在周一发布的推文《我在传统行业做数字化转型之预告篇》中,我提到互联网的发展和和竞争对传统行业起到了降维打击的作用,于是就有童鞋私下问我,为何这么说。今天就跟你聊聊这…

java aio复制文件_java复制文件的4种方式及拷贝文件到另一个目录下的实例代码...

尽管Java提供了一个可以处理文件的IO操作类。 但是没有一个复制文件的方法。 复制文件是一个重要的操作,当你的程序必须处理很多文件相关的时候。 然而有几种方法可以进行Java文件复制操作,下面列举出4中最受欢迎的方式。1. 使用FileStreams复制这是最经典的方式将一个文件的内…

BCVP开发者说第一期:Destiny.Core.Flow

沉静岁月,淡忘流年1项目简介Destiny.Core.FlowDestiny.Core.Flow是基于.NetCore平台,轻量级的模块化开发框架,Admin管理应用框架,旨在提升团队的快速开发输出能力,由常用公共操作类(工具类、帮助类&#xf…

.NET Core 取消令牌:CancellationToken

在 .NET 开发中,CancellationToken(取消令牌)是一项比较重要的功能,掌握并合理的使用 CancellationToken 可以提升服务的性能。特别在异步编程中,我常常会以创建 Task 的方式利用多线程执行一些耗时或非核心业务逻辑&a…

java char short区别_java 彻底理解 byte char short int float long double

遇到过很多关于 数值类型范围的问题了,在这做一个总结,我们可以从多方面理解不同数值类型的所能表示的数值范围在这里我们只谈论 java中的数值类型首先说byte:这段是摘自jdk中 Byte.java中的源代码从这里可以看出 byte的取值范围:…

程序员过关斩将--从未停止过的系统架构设计步伐

“首先,这篇文章肯定会得罪一些人“其次,此文只代表我个人的意见,仅供参考从分层说起谈到系统架构的分层和系统领域边界的划分,每个架构师,每个技术经理,甚至每个程序员都有自己的一套想法。无论是怎么样的…

java流上传文档把磁盘撑满_BOOT目录磁盘占用满处理

背景:Ubuntu:16.04查看已安装启动镜像dpkg --get-selections |grep linux-image这里会列出目前已经安装的启动镜像,一般分两种,一种状态为“install”,一种为“deinstall”对于"deinstall"的镜像,一般为镜像…

C# 9.0 正式发布了(C# 9.0 on the record)

翻译自 Mads Torgersen 2020年11月10日的博文《C# 9.0 on the record》 [1],Mads Torgersen 是微软 C# 语言的首席设计师,也是微软 .NET 团队的项目群经理。C# 9.0 正式发布正式宣布:C# 9.0 发布了!早在5月,我就写了一…

磁带最优存储问题java实现_磁带的最优存储问题(贪心选择)

算法设计n个程序的平均读取时间:(贪心策略)在该题目中,要考虑综合因素:长度和读取概率。要求n个程序的平均读取时间最短。按照贪心策略,则每个程序的读取时间都应该最短。故:(1)计算每个程序的长度和读取概率的乘积。(…

BCVP第2期:项目已完成升级.NET5.0

(是时候拿出来这种图了)1开心的锣鼓想必这两天最热闹的几个词语,就是c#9.0、.net5.0还有conf大会了吧,当然还有大一统。其实,早在2019年年中,就已经引入了.NET5.0了,然后从2020-03-16开始,就一直在说.NET5.…

java 1..0 openjdk_java-1.7.0-openjdk-i386和java-7-openjdk-i386有什么区别

两个OpenJDK是一样的.但是OpenJDK与Oracle JDK略有不同.阅读this post了解更多信息.您为OpenJDK获取两个选项的原因是PROBABLY,您有两个安装的OpenJDK副本(或两个不同的引用到系统上的同一目录).为了进一步调查,请尝试使用ls -lh /usr/lib / jvm. /usr/lib / jvm通常是Java安装…

linux java升级版本_为嵌入式Linux设备实现更新/升级系统

我有一个在嵌入式Linux设备上运行的应用程序,并且偶尔会对软件进行更改,有时也会对根文件系统甚至已安装的内核进行更改 .在当前的更新系统中,只删除旧应用程序目录的内容,并在其上复制新文件 . 当对根文件系统进行更改时&#xf…

如何在ASP.NetCore增加文件上传大小

关注架构师高级俱乐部开启架构之路不定期福利发放哦~架构师高级俱乐部读完需要7分钟速读仅需 3 分钟/ 如何在核心中增加文件 ASP.NET 大小 /从ASP.NET 2.0开始最大请求正文大小限制为30MB (28.6 MiB)。在正常情况下,无需增加 HTTP 请求 body …

java完全二叉树最小堆_Java实现最小堆一

Java实现最小堆一堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。最大堆和最小堆是二叉堆的两种形式。最大堆:根结点的键值是所有堆结点键值中最大者。最小堆:根结点的键值是所有堆结…

一个 Task 不够,又来一个 ValueTask ,真的学懵了!

一:背景 1. 讲故事前几天在项目中用 MemoryStream 的时候意外发现 ReadAsync 方法多了一个返回 ValueTask 的重载,真是日了狗了,一个 Task 已经够学了,又来一个 ValueTask,晕,方法签名如下:publ…

java class类型参数_使用Class对象实例化Java类型参数/ generic

如何实例化Java泛型对象,该对象仅接受类或参数给出的类型参数宾语?例如:通常,可以使用以下语法实例化Integer对象的ArrayList:ArrayList foo new ArrayList();但是,给定一个Class诸如Integer.class之类的对象,怎么能创建一个类似的ArrayList…

Magicodes.IE 3.0重磅设计畅谈

Magicodes.IE 3.0重磅设计畅谈总体设计图Magicodes.IE导入导出通用库,支持Dto导入导出、模板导出、花式导出以及动态导出,支持Excel、Csv、Word、Pdf和Html。IE在去年年底重构一次之后,经过这么长时间的迭代,又迎来了瓶颈。根据本…

php引用类,thinkphp引用类的使用

比如发送邮件类phpmailer1.将核心文件放入ORG目录下2.在使用的地方,引入这个类文件如何引入呢?import(.ORG.phpmailer);这个表示引入当前项目中的ORG中的phpmailer.class.php文件3.引入之后就可以使用文件中的类了public function sendEmail() {import(.…

Net5 已经来临,让我来送你一个成功

没错,那就是“下载成功”。现在,已经可以急速下载.Net5 docker 镜像 .Net 5 进行今天已经正式发布,想必各位已经通过各种渠道了解到了此次发布的所有内容。并且也都体会到了这次凑成三连的金 scott 是什么效果(啊哈,三…