当前位置: 首页 > news >正文

C#Lock机制

C#Lock机制

https://blog.csdn.net/qq_39025293/article/details/84655433

定义:lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

Monitor 方法是静态的,不需要生成Monitor 类的实例就可以直接调用它们。在.NET Framework 中,每个对象都有一个与之关联的锁,对象可以得到并释放它以便于在任意时间只有一个线程可以访问对象实例变量和方法。

Lock语句可以说就是通过Monitor.Enter()和Monitor.Exit()实现的。

当Lock(lockInstance){}结构开始执行时调用Monitor.Enter(lockInstance)锁定lockInstance临界区,当该结构执行结束,调用monitor.Exit(lockInstance)释放lockInstance临界区。

原理:对于任何一个对象来说,它在内存中的第一部分放置的是所有方法的地址,第二部分放着一个索引,这个索引指向CLR中的SyncBlock Cache区域中的一个SyncBlock。当你执行Monitor.Enter(Object)时,如果object的索引值为负数,就从SyncBlock Cache中选取一个SyncBlock,将其地址放在object的索引中。这样就完成了以object为标志的锁定,其他的线程想再次进行Monitor.Enter(object)操作,将获得object的已经为正值的索引,然后就等待。直到索引变为负数,即调用Monitor.Exit(object)将索引变为负数,等待的线程开始执行。


注意:

1.lock不能锁定空值,但Null是不需要被释放的。
2.lock不能锁定string类型,虽然它也是引用类型的。因为字符串类型被CLR“暂留”。即整个程序中任何给定字符串都只有一个实例,具有相同内容的字符串都代表着同一个实例。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中与该字符串具有相同内容的字符串。因此,最好锁定不会被暂留的私有或受保护成员。

实例:

测试结果 :

可以看出,str01和str02是两个string类型的变量,但是当lock(str01)之后,str02变成了临界区被锁定导致th2中lock(){}体处于等待状态。这就对应了只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中与该字符串具有相同内容的字符串这句话。
3.lock锁定的对象是一个程序块的内存边界
4.值类型不能被lock,因为前文标红字的“对象被释放”,值类型不是引用类型的

5.lock就避免锁定public 类型或不受程序控制的对象。
例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。
使用lock(this)的时候,类的成员变量的值可能会被不在临界区的方法改值了

应用场景:经常会应用于防止多线程操作导致公用变量值出现不确定的异常,用于确保操作的安全性。

实例:

测试结果:

可以看出,当线程th执行lock(stu)之后,stu成为临界区被锁定。其他线程等待该lock(){}执行完成stu被释放后,开始执行。

另外,由于我是学习Unity游戏开发的,这里插入一句,在Unity中是不允许在子线程中访问Unity的一些属性例如Transfrom等。我猜测这是因为防止因为子线程的使用不当,导致Unity底层数据的错乱。所以Unity直接使用Lock机制阻止用户直接在子线程中使用Unity的一些特定属性。
————————————————
版权声明:本文为CSDN博主「戎夏不姓夏」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39025293/article/details/84655433

 

 

 

 

 

相关文章:

  • AssetBundle中的一个坑-DeterministicAssetBundle与文件名
  • Unity Asset Bundle 的BuildAssetBundleOptions
  • daaoling / daaoling.github.io
  • 一个灵活的AssetBundle打包工具
  • BuildPipeline.BuildAssetBundleExplicitAssetNames
  • Unity5.x shader打包AssetBundle总结
  • Unity 加载AssetBundle
  • Unity开发(三) AssetBundle同步异步引用计数资源加载管理器
  • Unity脚本运行时更新带来了什么?
  • UE4 补丁更新(基于Http)
  • UE4 Pak加载
  • Unity3D Shader加载时机和预编译
  • ShaderVariantCollection解决shader_feature丢失
  • 一次UNITY闪退问题的定位心得
  • Unity AssetBundle打包 , BuildAssetBundleOptions
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • 10个最佳ES6特性 ES7与ES8的特性
  • Angular 2 DI - IoC DI - 1
  • AWS实战 - 利用IAM对S3做访问控制
  • Git初体验
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • mongodb--安装和初步使用教程
  • mysql常用命令汇总
  • node学习系列之简单文件上传
  • Python连接Oracle
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 聚类分析——Kmeans
  • 区块链共识机制优缺点对比都是什么
  • 我从编程教室毕业
  • 一个完整Java Web项目背后的密码
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • AI算硅基生命吗,为什么?
  • 如何用纯 CSS 创作一个货车 loader
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • ./和../以及/和~之间的区别
  • .libPaths()设置包加载目录
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .net访问oracle数据库性能问题
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • @angular/cli项目构建--Dynamic.Form
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [Android View] 可绘制形状 (Shape Xml)
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BZOJ 1040] 骑士
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
  • [c]统计数字