本文主要讲解.Net基于Monitor.Enter和lock实现互斥锁


Monitor.Enter实现

相比前面的锁来说,混合锁的性能更高,任何引用类型的对象都可以做为锁对象,不需要事先创建指定类型的实例,并且设计的非托管的资源由.Net运行时自动释放,不需要手动调用释放函数,获取和释放混合锁需要使用System.Threading.Monitor类中的函数。使用Monitor使用混合锁的例子如下:

using System;
using System.Threading; namespace MixedLockDemo
{
/// <summary>
/// 混合锁Demo
/// </summary>
public static class NitiveLockDemo
{
private static readonly object _lock = new();
private static int _counterA = 0;
private static int _counterB = 0; public static void IncrementCounters()
{
//定义变量
var lockObject = _lock;
bool lockTaken = false;
try
{
Console.WriteLine($"开始执行锁前的数值:{_counterA},{_counterB}");
// 获取锁
Monitor.Enter(_lock, ref lockTaken);
++_counterA;
++_counterB; }
finally
{
//如果锁wei
if (!lockTaken)
{
Monitor.Exit(lockObject);
}
}
} public static void GetCounters(ref int counterA, ref int coubterB)
{
//定义变量
var lockObject = _lock;
bool lockTaken = false;
try
{
Monitor.Enter(lockObject, ref lockTaken);
counterA = _counterA;
coubterB = _counterB;
}
finally
{
if (!lockTaken)
{
Monitor.Exit(lockObject);
}
}
}
}
}

lock实现

C# 调用lock语句来简化System.Threading.Monitor类获取和释放锁的代码。以下是使用lock的实例

namespace MixedLockDemo
{
/// <summary>
/// 封装后的lock语句使用
/// </summary>
public static class PackageingLockDemo
{
private static readonly object _lock = new();
private static int _counterA = 0;
private static int _counterB = 0; /// <summary>
/// 增加
/// </summary>
public static void IncrementCounters()
{
lock (_lock)
{
++_counterA;
++_counterB;
}
} /// <summary>
/// 获取
/// </summary>
/// <param name="counterA"></param>
/// <param name="coubterB"></param>
public static void GetCounters(ref int counterA, ref int coubterB)
{
lock (_lock)
{
counterA = _counterA;
coubterB = _counterB;
}
}
}
}

概念

混合锁的特征是在获取失败后像自旋锁一样重试一定的次数,超过一定次数后再安排线程进入等待状态,


混合所的好处是,如果第一次获取锁失败,但其他线程马上释放了锁,当前线程在下一轮重试可以获取成功,不需要执行毫秒级的线程调度处理;如果其他线程在短时间内没有释放锁,线程会在超过重试次数后进入等待状态,以避免消耗CPU资源,因此混合锁适用于大部分场景。


所有引用类型的对象都可以作为锁对象的原理是,引用类型的对象都有一个32位(4字节)的对象头,对象头的位置在对象地址之前,例如对象的内容在内存地址中0×7fff2008时,对象头的地址在0×7fff2004。在32位的对象头中,高6位用于储存标志,低26位储存的内容根据标志而定,可以存储当前获取该锁的线程Id和进入次数(用入实现可重入),也可以储存同步块索引。


同步块是一个包含所属线程对象,进入次数和事件对象的对象。事件对象可用于让线程进入等待状态和唤醒线程,同步块会按需要创建(如果只是用自旋锁可获取锁则无需创建)并自动释放,.Net运行时内部有一个储存同步块的数组,同步块索引指的是同步块在这个数组中的索引.

释放锁和获取锁流程图


本文基于.Net Core底层入门总结内容

如有哪里讲得不是很明白或是有错误,欢迎指正

如您喜欢的话不妨点个赞收藏一下吧

个人微信

一文带你.Net混合锁和lock语句的更多相关文章

  1. 一文带你了解elasticsearch

    一文带你了解elasticsearch cxf2102100人评论160人阅读2019-07-02 21:31:36   elasticsearch es基本概念 es术语介绍 文档Document ...

  2. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

  3. 一文带你读懂zookeeper在大数据生态的应用

    一个执着于技术的公众号 一.简述 在一群动物掌管的世界中,动物没有人类聪明的思想,为了保持动物世界的生态平衡,这时,动物管理员-zookeeper诞生了. 打开Apache zookeeper的官网, ...

  4. 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

    一. 监视锁(Monitor和lock) 1. Monitor类,限定线程个数的一把锁,两个核心方法: Enter:锁住某个资源. Exit:退出某一个资源. 测试案例:开启5个线程同时对一个变量进行 ...

  5. Istio是啥?一文带你彻底了解!

    原标题:Istio是啥?一文带你彻底了解! " 如果你比较关注新兴技术的话,那么很可能在不同的地方听说过 Istio,并且知道它和 Service Mesh 有着牵扯. 这篇文章可以作为了解 ...

  6. 一文带您了解5G的价值与应用

    一文带您了解5G的价值与应用 5G最有趣的一点是:大多数产品都是先有明确应用场景而后千呼万唤始出来.而5G则不同,即将到来的5G不仅再一次印证了科学技术是第一生产力还给不少用户带来了迷茫——我们为什么 ...

  7. 【转帖】Istio是啥?一文带你彻底了解!

    Istio是啥?一文带你彻底了解! http://www.sohu.com/a/270131876_463994 原始位置来源: https://cizixs.com 如果你比较关注新兴技术的话,那么 ...

  8. 一文带你了解 C# DLR 的世界

    一文带你了解 C# DLR 的世界 在很久之前,我写了一片文章dynamic结合匿名类型 匿名对象传参,里面我以为DLR内部是用反射实现的.因为那时候是心中想当然的认为只有反射能够在运行时解析对象的成 ...

  9. 一文带你看清HTTP所有概念(转)

    一文带你看清HTTP所有概念   上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就来深究一下 HTTP 的特性.我们接着上篇文章没有说完的 HTTP 标头继 ...

随机推荐

  1. babylin使用思路

  2. Redis 分布式锁|从青铜到钻石的五种演进方案

    缓存系列文章: 缓存实战(一):20 图 |6 千字|缓存实战(上篇) 缓存实战(二):Redis 分布式锁|从青铜到钻石的五种演进方案 缓存实战(三):分布式锁中的王者方案 - Redisson 上 ...

  3. [Java] HOW2J(Java中级)

    异常 定义:导致程序正常流程被中断的事件 异常处理常见手段 try catch:将可能抛出异常的代码放在try的块中,一旦出现异常就跳转到catch的块中处理 throws/throw:不在本模块处理 ...

  4. 解析CentOS 8上的Xrdp服务器安装

    解析CentOS 8上的Xrdp服务器安装   Linux系统技术交流QQ群(915246)验证问题答案:刘遄 导读 Xrdp 是 Microsoft 远程桌面协议 (RDP) 的开源实现,允许您以图 ...

  5. 文件不同 diff --brief XX YY

    文件不同 diff --brief XX YY 文件不同 --哪些位置 diff -c XX YY 9.diff命令 diff命令用于比较多个文本文件的差异,格式为"diff [参数] 文件 ...

  6. Apache Flink 1.12.0 正式发布,DataSet API 将被弃用,真正的流批一体

    Apache Flink 1.12.0 正式发布 Apache Flink 社区很荣幸地宣布 Flink 1.12.0 版本正式发布!近 300 位贡献者参与了 Flink 1.12.0 的开发,提交 ...

  7. git/repo常用命令

    Git作为广受欢迎的一款版本控制工具,它该如何通过命令行使用呢?本文为你揭晓浓缩精华精华版:git常用命令一览,含部分repo操作. 代码下载 repo init -- -->初始化需要下载的分 ...

  8. Centos7 docker容器启动后添加端口映射

    docker容器启动后添加端口映射的两种方法: 一.通过修改防火墙策略添加端口映射 docker容器已创建好,但是想在容器内配置tomcat监控,需要新的端口去访问,但是映射时没有映射多余端口,此时, ...

  9. Mybatis Plus 多租户架构实现(完美教程)

    一.背景介绍 多租户技术或称多重租赁技术,简称SaaS,是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性. 简单讲 ...

  10. 19c PDB数据泵迁入

    1.问题描述 用数据泵进行pdb的迁入迁出,模拟测试将其他库的数据导入到19cpdb中 2.环境介绍 source:12.2.0.1.0 target:19.0.0.0.0 3.源端制造数据 创建表空 ...