本文主要讲解.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. Spring MVC工作原理及源码解析(四) ViewResolver实现原理及源码解析

    0.ViewResolver原理介绍 根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Mode ...

  2. 阿里云RDS数据库到期实例被清除,别急着哭(阿里没有删库跑路),或许还有一线生机

    阿里资源到期未续费,数据保存期限: ECS实例的保存期是15天. Redis实例的保存期是7天. RDS实例的保存期也是7天. 过期当天会收到一条短信: [阿里云]尊敬的用户:您的RDS实例(实例ID ...

  3. Cookie&Session-授课

    1 会话技术 1.1 会话管理概述 1.1.1 什么是会话 会话:浏览器和服务器之间的多次请求和响应 为了实现一些功能,浏览器和服务器之间可能会产生多次的请求和响应,从浏览器访问服务器开始,到访问服务 ...

  4. 手写Promise中then方法返回的结果或者规律

    1. Promise中then()方法返回来的结果或者规律 我们知道 promise 的 then 方法返回来的结果值[result]是由: 它指定的回调函数的结果决定的 2.比如说下面这一段代码 l ...

  5. 24.Qt Quick QML-Canvas和Context2D详解

    1.Canvas介绍Canvas是一个允许绘制直线和曲线.简单和复杂的形状.图形和引用的图形图像.它还可以添加文本.颜色.阴影.渐变和图案,并执行低级别像素操作.Canvas输出可以另存为图像文件或序 ...

  6. 网络协议 SNMP- Windows10无简单SNMP协议服务器配置

    原因:Windwos10 1809后更新版本,无启动SNMP协议服务器可选配置项. 解决: 1.打开设置中的[开发人员模式],设置->更新与安全->开发者选项->开发人员模式 2.添 ...

  7. netperf对比

    netperf -H 10.1.60.141 -t TCP_STREAM -l 60  -p 10082 netperf -H 10.1.60.141 -t UDP_STREAM -l 60  -p ...

  8. github祥解

    github介绍 安装 仓库创建& 提交代码 代码回滚 工作区和暂存区 撤销修改 删除操作 远程仓库 分支管理 多人协作 github使用 忽略特殊文件.gitignore 为什么要用版本控制 ...

  9. MySQL 查询操作

    目录 基本语法 查询常量 查看表达式 查询函数 查询指定字段 查询所有列 列别名 表别名 条件查询 条件查询运算符 逻辑查询运算符 排序与分页 排序查询(order by) 排序方式 limit 分组 ...

  10. python基础之流程控制(if判断和while、for循环)

    程序执行有三种方式:顺序执行.选择执行.循环执行 一.if条件判断 1.语句 (1)简单的 if 语句 (2)if-else 语句 (3)if-elif-else 结构 (4)使用多个 elif 代码 ...