C#中Lock的秘密
一、概要
本文主要讲解在c#中lock关键字的用法以及需要注意的坑。帮助大家避免使用不当造成的bug。
作用:lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical p),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。在多线程中,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。
缺点: 多线程中频繁使用lock会造成性能损耗。
二、详细内容
(1)使用
以下是lock在单例中使用的,大家可以看到在Instance中有两个if判断_instance是否为空。为什么?因为lock在执行的过程中会有性能损耗如果已经初始化过了之后就不要在走lock加锁了,多线程中只读单例 对象是不会造成‘脏读’数据的。那么最外层的if就完美避免了lock的缺点。
public class Demo1
{private static readonly object _lockObj = new object();private static Demo1 _instance;public static Demo1 Instance{get{if (_instance == null){lock (_lockObj){if (_instance == null){_instance = new Demo1();}}}return _instance;}}private Demo1() { }public List<string> GetData() {return new List<string>();}
}
(2)注意事项及原理
2.1注意事项
当同步对共享资源的线程访问时,请锁定专用对象实例(例如,private readonly object balanceLock = new object();)或另一个不太可能被代码无关部分用作 lock 对象的实例。避免对不同的共享资源使用相同的 lock 对象实例,因为这可能导致死锁或锁争用。具体而言,避免将以下对象用作 lock 对象:
this(调用方可能将其用作 lock)。
Type 实例(可以通过 typeof 运算符或反射获取)。
字符串实例,包括字符串文本,(这些可能是暂存的)。
尽可能缩短持有锁的时间,以减少锁争用。
在 lock 语句的正文中不能使用 await 运算符。
2.2原理(以下内容比较浅显,太深究内容一篇文章写不完)
Q1:大家会注意到,为什么要在lock的圆括号里放一个引用类型object?为什么不可以放一个值类型例如int?
A1:因为如果使用了值类型例如int作为lock锁定的对象,lock圆括号中的入参是object类型当传入了值类型会对传入的对象类型进行转换,那么在IL层面会对值类型进行一次装箱(box)操作。那么这种情况下就不具备lock锁定需要用到专用对象的稳定性了。
IL_0002:ldloc.0
IL_0003:box [mscorlib]System.Int32
A2:第二个原因这个就需要追溯到“值类型”和“引用类型”的基类,大家都知道引用类型的基类是object、值类型的基类是ValueType这两种基类本质的区别如下:
值类型:构造中不包含同步块索引。
引用类型:构造中包含同步块索引。
除了c#语法不支持以外它不适宜作为lock圆括号中的锁定对象的原因就是没有同步块索引。
C#中Lock的秘密相关推荐
- java 中lock,java中lock获取锁的四种方法
在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...
- CNN 分类古代陶器,表现超过考古专家,解决“考古学中的肮脏秘密”
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 转自 | 大数据文摘 来源 | sciencedaily 编译 | ...
- java lock的原理,Java中Lock原理探究
在对于lock锁的使用上,很多人只是掌握了最基础的方法,但是对实现的过程不是很清楚.这里我们对lock锁功能的实现进行分析,以ReentrantLock为例,分析它的锁类型,并对相关的调用方法进行展示 ...
- 一个线程中lock用法的经典实例
1 /* 2 该实例是一个线程中lock用法的经典实例,使得到的balance不会为负数 3 同时初始化十个线程,启动十个,但由于加锁,能够启动调用WithDraw方法的可能只能是其中几个 4 作者: ...
- C#多线程中lock的用法
最近在看些c#的代码,发现很多是以前没有接触到了,只能上网查,把比较好的整理下来. 经常碰到同时需要对某个数据进行操作,或者对某个文件进行读写操作,对于这些操作我们以前往往不能很好的进行处理,自从C# ...
- 数组传参中形参的秘密,以及数组名当作函数实际参数的特点,以及二维数组,以及外部变量和全局变量
1.数组传参中形参的秘密 第三行:形参中不存在数组的概念,即便是中括号约定了数组的大小,也无效. 第二十行:传递的是一个地址,是数组的首地址. 数组名代表了整个数组的首地址. 第二十一行:第一个元素的 ...
- C#中lock死锁实例教程
C#中lock死锁实例教程 http://www.jb51.net/article/54309.htm posted on 2016-10-24 23:00 时空观察者9号 阅读(...) 评论(.. ...
- c# 多线程中lock用法的经典实例
一.Lock定义 lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行, ...
- 一文带你理解Java中Lock的实现原理
转载自 一文带你理解Java中Lock的实现原理 当多个线程需要访问某个公共资源的时候,我们知道需要通过加锁来保证资源的访问不会出问题.java提供了两种方式来加锁,一种是关键字:synchron ...
最新文章
- 查出引起死锁的进程和SQL语句
- mysql的语句分类,查询、子查询及连接查询
- 【js】版本号对比处理方案
- shell中三种引号的区别
- kafka消息存储原理及查询机制
- boost::geometry::model::d3::point_xyz用法的测试程序
- 微软的 SQL Server 你学会了吗?
- OData model cache logic in gateway system
- 日期格式无法识别 oracle,Oracle时间统计 - 不以物喜-不以己悲的个人空间 - OSCHINA - 中文开源技术交流社区...
- codeforces 1073E
- spark java 案例_Spark入门案例
- python开发自动化创建一个任务下发到手机_django2 +requests+ddt+unittest+HTMLestRunner接口自动化测试平台...
- 2016-06-07【普元EOS Studio】
- 剑指offer刷题记录
- 堪萨斯大学计算机硕士,堪萨斯大学计算机专业设置及申请条件汇总 你get到了吗?...
- Gitlab 登录报422错误,账号密码是对的?
- PS字体加粗的小方法、、
- java使用字符流读取文件
- deepin安装docker
- 从零认识 无标度网络