一、概要

本文主要讲解在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的秘密相关推荐

  1. java 中lock,java中lock获取锁的四种方法

    在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...

  2. CNN 分类古代陶器,表现超过考古专家,解决“考古学中的肮脏秘密”

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 转自 | 大数据文摘 来源 | sciencedaily 编译 | ...

  3. java lock的原理,Java中Lock原理探究

    在对于lock锁的使用上,很多人只是掌握了最基础的方法,但是对实现的过程不是很清楚.这里我们对lock锁功能的实现进行分析,以ReentrantLock为例,分析它的锁类型,并对相关的调用方法进行展示 ...

  4. 一个线程中lock用法的经典实例

    1 /* 2 该实例是一个线程中lock用法的经典实例,使得到的balance不会为负数 3 同时初始化十个线程,启动十个,但由于加锁,能够启动调用WithDraw方法的可能只能是其中几个 4 作者: ...

  5. C#多线程中lock的用法

    最近在看些c#的代码,发现很多是以前没有接触到了,只能上网查,把比较好的整理下来. 经常碰到同时需要对某个数据进行操作,或者对某个文件进行读写操作,对于这些操作我们以前往往不能很好的进行处理,自从C# ...

  6. 数组传参中形参的秘密,以及数组名当作函数实际参数的特点,以及二维数组,以及外部变量和全局变量

    1.数组传参中形参的秘密 第三行:形参中不存在数组的概念,即便是中括号约定了数组的大小,也无效. 第二十行:传递的是一个地址,是数组的首地址. 数组名代表了整个数组的首地址. 第二十一行:第一个元素的 ...

  7. C#中lock死锁实例教程

    C#中lock死锁实例教程 http://www.jb51.net/article/54309.htm posted on 2016-10-24 23:00 时空观察者9号 阅读(...) 评论(.. ...

  8. c# 多线程中lock用法的经典实例

    一.Lock定义     lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行, ...

  9. 一文带你理解Java中Lock的实现原理

    转载自   一文带你理解Java中Lock的实现原理 当多个线程需要访问某个公共资源的时候,我们知道需要通过加锁来保证资源的访问不会出问题.java提供了两种方式来加锁,一种是关键字:synchron ...

最新文章

  1. 查出引起死锁的进程和SQL语句
  2. mysql的语句分类,查询、子查询及连接查询
  3. 【js】版本号对比处理方案
  4. shell中三种引号的区别
  5. kafka消息存储原理及查询机制
  6. boost::geometry::model::d3::point_xyz用法的测试程序
  7. 微软的 SQL Server 你学会了吗?
  8. OData model cache logic in gateway system
  9. 日期格式无法识别 oracle,Oracle时间统计 - 不以物喜-不以己悲的个人空间 - OSCHINA - 中文开源技术交流社区...
  10. codeforces 1073E
  11. spark java 案例_Spark入门案例
  12. python开发自动化创建一个任务下发到手机_django2 +requests+ddt+unittest+HTMLestRunner接口自动化测试平台...
  13. 2016-06-07【普元EOS Studio】
  14. 剑指offer刷题记录
  15. 堪萨斯大学计算机硕士,堪萨斯大学计算机专业设置及申请条件汇总 你get到了吗?...
  16. Gitlab 登录报422错误,账号密码是对的?
  17. PS字体加粗的小方法、、
  18. java使用字符流读取文件
  19. deepin安装docker
  20. 从零认识 无标度网络

热门文章

  1. 蓝桥杯——快速排序(2018JavaB组第5题9分)
  2. .NET中RabbitMQ的使用
  3. 版本控制介绍以及常用的版本控制工具
  4. SQL中触发器的使用
  5. 【开发工具之Spring Tool Suite】6、用Spring Tool Suite简化你的开发
  6. 在线自动下载最新版本jquery
  7. mysql配置-django
  8. 数组面试题--数组求和
  9. Ext4.2文件目录及页面默认导入文件
  10. java--用 * 打印出各种图形(新手请进)