• C# 学习Lock关键字


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

    代码如下:
    在这里插入图片描述
    上面代码应该都能看懂,可以实现在某一时刻,只允许一个线程访问功能,避免多个线程同时访问。我们来看一下Lock的实现,其实Lock是C#的语法糖,本质上是C#的Monitor类,等价于下面代码:
    在这里插入图片描述
    我们接着讲。我们还是看lock(_lockObj)这一行,简单地想一想,lock关键字把_lockObj对象锁住了,别的线程就进不来了,那它是怎么锁的呢?是在对象上打了标记吗?是把线程ID打了标记吗?我们先看一下堆中_lockObj的对象结构。如下图:
    在这里插入图片描述
    可以看到,对象在堆中除了数据区以外,还有两片区域:MethodTableRef、SyncBlockValue。其中MethodTableRef是指向MethodTable中这个类型(Type)定义,简单说就是这个对象是什么class定义的。SyncBlockValue 就是Lock的重点了。如下图:
    ![
    SyncBlockValue 这个值为DWORD类型,占用4个字节,也就是32位。一般将32位分为两段,前6位用以表示不同的功能(这里假设第5位是锁定位),后26位用以表示对象的hash值、或者是SyncBlock的索引值。
    上锁过程:线程AB几乎同时访问Lock语句,A先到Lock查找第5位是否有值,无值则到图中的g_pSyncTable申请一个同步锁SyncBlock,并且在同步锁中记录A的线程ID信息,最后将同步锁地址赋值给后26bit,这样_lockObj就被线程A锁住。B后到同样查找第5位是否有值,发现被锁住了,然后去SyncBlock检查锁住的线程ID是否和自己一致,不一致的话,它就会一直等待,直到线程A释放锁。

    注意:

    1. Lock的是引用类型的对象,string类型除外,不能是值类型,编译会报错,并且不能为空。
    2. Lock推荐的做法是使用静态的、只读的、私有的锁定对象。
    3. 保证Lock的对象在外部无法修改才有意义,如果lock的对象在外部改变了,对其他线程就会畅通无阻,失去了Lock的意义。

    以上是自己结合资料的理解,有错误请指正。

  • 相关阅读:
    初识OpenGL (-)纹理(Texture)
    【云原生】Kubernetes介绍
    数商云SCM系统订单收货场景介绍,探索采购新模式,提升汽车服务企业运营水平
    Delta Lake: High-Performance ACID Table Storage over Cloud Object Stores
    EFK代替ELK方案7.17.3
    第二十三章《斗地主游戏》第1节:斗地主项目简介
    “对症下药”,高效控价——控价方法详解
    位图BitMap不好用?那来看看进化版本的RoaringBitmap,包您满意
    ERP生产作业控制
    Git---当本地分支和远程分支都被删除时,如何处理?
  • 原文地址:https://blog.csdn.net/Ling_SevoL_Y/article/details/127793764