一文带你了解.Net基于Threading.Mutex实现互斥锁

本文主要讲解.Net基于Threading.Mutex实现互斥锁

基础互斥锁实现

基础概念:和自旋锁一样,操作系统提供的互斥锁内部有一个数值表示锁是否已经被获取,不同的是当获取锁失败的时候,它不会反复进行重试,而且让线程进入等待状态,并把线程对象添加到锁关联的队列中,另一个线程释放锁时会检查队列中是否有线程对象,如果有则通知操作系统唤醒该线程,因为获取锁的线程对象没有进行运行,即使锁长时间不释放也不会消耗CPU资源,但让线程进入等待状态和从等待状态唤醒的时间比自旋锁重试的纳秒级时间要长

windows和linux的区别

在windows系统上互斥锁通过CreateMuteEx函数创建,获取锁时将调用WaitForMultipleObjectsEx函数,释放锁将调用ReleaseMutex函数,线程进入等待状态和唤醒由系统操作
在Linux上互斥锁对象由NetCore的内部接口模拟实现,结果包含锁的状态值以及等待线程队列,每个托管线程都会关联一个pthread_mutex_t对象和一个pthread_cond_t对象,这两个对象友pthread类库提供,获取锁失败线程会调价到队列pthread_cond_wait函数等待,另一个线程释放锁时看到队列中有线程则调用pthread_cond_signal函数唤醒。

基础互斥锁代码实现

 public static class MutexDemo
    {
        private static readonly Mutex _lock = new Mutex(false, null);
        private static int _counterA = 0;
        private static int _counterB = 0;

        public static void IncrementCounters()
        {
            //获取锁
            _lock.WaitOne();
            try
            {
                ++_counterA;
                ++_counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

        public static void GetCounters(out int counterA, out int counterB)
        {
            _lock.WaitOne();
            try
            {
                counterA = _counterA;
                counterB = _counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

    }

互斥锁(递归锁)

基础概念:Mutex提供的锁可重入,已经获取锁的线程可以再次执行获取锁的操作,但释放锁的操作也要执行对应的相同次数,可重入的锁又叫递归锁。

实现原理:递归锁内部使用一个计数器记录进入次数,同一个线程每获取一次就加1,释放一次就减1,减1后如果计算器为0就执行真正的释放操作。递归锁在单个函数中使用没有意义,一般嵌套在多个函数中

代码实现

public static class MutexRecursionDemo
    {
        private static Mutex _lock = new Mutex(false, null);
        private static int _counterA = 0;
        private static int _counterB = 0;

        public static void IncrementCountersA()
        {
            //获取锁
            _lock.WaitOne();
            try
            {
                ++_counterA;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

        public static void IncrementCountersB()
        {
            //获取锁
            _lock.WaitOne();
            try
            {
                ++_counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

        public static void IncrementCounters()
        {
            //获取锁
            _lock.WaitOne();
            try
            {
                IncrementCountersA();
                IncrementCountersB();
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

        public static void GetCounters(out int counterA, out int counterB)
        {
            _lock.WaitOne();
            try
            {
                counterA = _counterA;
                counterB = _counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }
    }

互斥锁(跨进程使用)

基础概念:Mutex支持夸进程使用,创建是通过构造函数的第二个参数name传入名称,名称以Walterlv.Mutex开始时同一个用户的进程共享拥有此名称的锁,如果一个进程中获取了锁,那么在释放该锁前另一个进程获取同样名称的锁需要等待,如果进程获取了锁,但是在退出之前没有调用释放锁的方法,那么锁会被自动释放,其他当前正在等待锁的京城会受到AbandonedMuteException异常。

linux实现方式是通过临时文件的方式实现

实现代码

public static class MutexDemo
    {
        private static Mutex _lock = new Mutex(false, @"Walterlv.Mutex");
        private static int _counterA = 0;
        private static int _counterB = 0;

        public static void IncrementCounters()
        {
            //获取锁
            _lock.WaitOne();
            try
            {
                ++_counterA;
                ++_counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }

        public static void GetCounters(out int counterA, out int counterB)
        {
            _lock.WaitOne();
            try
            {
                counterA = _counterA;
                counterB = _counterB;
            }
            finally
            {
                //释放锁
                _lock.ReleaseMutex();
            }
        }
    }

以上代码只需要复制一份,在多个程序中启动,调用MutexDemo.IncrementCounters()则可以看到效果

到此这篇关于一文带你了解.Net基于Threading.Mutex实现互斥锁的文章就介绍到这了,更多相关.Net 互斥锁内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • .NET中STAThread的使用详解

    在WindowForm应用程序中主要的线程,是采用一种称为「Single-Threaded Apartment(STA)」的线程模型.这个STA线程模型,在线程内加入了讯息帮浦等等机制,减少开发人员撰写窗口程序的工作量. 而在开发类别库的时候,如果要使用类似的STA线程模型,可以使用下列的程序代码提供的类别来完成. 复制代码 代码如下: namespace CLK.Threading{    public class STAThread    {        // Enum        pr

  • .Net基于Thread实现自旋锁的三种方式

    基于Thread.SpinWait实现自旋锁 实现原理:基于Test--And--Set原子操作实现 使用一个数据表示当前锁是否已经被获取 0表示未被索取,1表示已经获取 获取锁时会将_lock的值设置为1 然后检查修改前的值是否等于0, 优点: 不使用Thread.SpinWait方法,重试的方法体会为空,CPU会使用它的最大性能来不断的进行赋值和比较指令,会浪费很大的性能,Thread.SpinWait提示CPU当前正在自旋锁的循环中,可以休息若干个时间周期 使用自旋锁需要注意的问题,自旋锁

  • .NET Windows 多线程thread编程

    进程:工厂搬砖头,10个工人搬完1000个砖头 线程:每个工人,搬完100个砖头,就是一个任务 采用线程,异步搬: 手工去搬,10个工人同时搬,效率高,异步执行,如果不采用线程,等第一个人搬完后第二个人才搬,那就慢了 什么时候不能用线程: 如果要用小车来搬,只有一个小车,那么,在这样的情况下,就不应该用线程,因为只有一个小车,各个线程都在争夺和等待这个小车,所以不能用线程.如果这个时候还要用线程,则导致资源浪费, 因为每个线程都有自己的资源,如包工头(CPU)同一时间要管理这10个工人,而只有一

  • .NET 6线程池ThreadPool实现概述

    目录 前言 任务的调度 基本调度单元 IThreadPoolWorkItem 实现类的实例. Task 全局队列 本地队列 偷窃机制 Worker Thread 的生命周期管理 线程注入实验 .NET 5 实验一 默认线程池配置 .NET 5 实验二 调整 ThreadPool 设置 .NET 5 实验三 tcs.Task.Wait() 改为 Thread.Sleep .NET 6 实验一 默认 ThreadPool 设置 .NET 6 实验二 调整 ThreadPool 设置 .NET 6 实

  • .NET提取 Thread 中返回值详情

    目录 一..NET 2.0+ 二..NET 4.0 + 三..NET 4.5 + 以下文章来源于公众号DotNetCore实战  Igor Bendrup: 关于如何获取 Thread 中的返回值,不同的版本有不同的解决方案. 一..NET 2.0+ 你可以直接使用 Thread 对象,然后你可以使用闭包(声明变量并在 lambda 中捕获它),参考如下代码: object result = null; Thread thread = new System.Threading.Thread(()

  • 一文带你了解.Net基于Threading.Mutex实现互斥锁

    本文主要讲解.Net基于Threading.Mutex实现互斥锁 基础互斥锁实现 基础概念:和自旋锁一样,操作系统提供的互斥锁内部有一个数值表示锁是否已经被获取,不同的是当获取锁失败的时候,它不会反复进行重试,而且让线程进入等待状态,并把线程对象添加到锁关联的队列中,另一个线程释放锁时会检查队列中是否有线程对象,如果有则通知操作系统唤醒该线程,因为获取锁的线程对象没有进行运行,即使锁长时间不释放也不会消耗CPU资源,但让线程进入等待状态和从等待状态唤醒的时间比自旋锁重试的纳秒级时间要长 wind

  • Python Threading 线程/互斥锁/死锁/GIL锁

    导入线程包 import threading 准备函数线程,传参数 t1 = threading.Thread(target=func,args=(args,)) 类继承线程,创建线程对象 class MyThread(threading.Thread) def run(self): pass if __name__ == "__main__": t = MyThread() t.start() 线程共享全面变量,但在共享全局变量时会出现数据错误问题 使用 threading 模块中的

  • 一文带你了解Python 四种常见基础爬虫方法介绍

    一.Urllib方法 Urllib是python内置的HTTP请求库 import urllib.request #1.定位抓取的url url='http://www.baidu.com/' #2.向目标url发送请求 response=urllib.request.urlopen(url) #3.读取数据 data=response.read() # print(data) #打印出来的数据有ASCII码 print(data.decode('utf-8')) #decode将相应编码格式的

  • 一文带你了解Mysql主从同步原理

    目录 Mysql 主从同步原理简析 1.什么是主从 2.为什么要搞主从呢? 3.如何实现主从同步呢? 4.mysql 主从同步的原理 Mysql 主从同步原理简析 在开始讲述原理的情况下,我们先来做个知识汇总, 究竟什么是主从,为什么要搞主从,可以怎么实现主从,mysql主从同步的原理 1.什么是主从 其实主从这个概念非常简单 主机就是我们平常主要用来读写的服务,我们称之为master(主人.主宰) 从机就是主机进行的一个扩展,他一般不会主动用来读写,我们称之为slave( [sleɪv] 奴隶

  • 一文带你走进js-数据类型与数据结构的世界

    目录 2. 数据类型 2.1 原始类型(6 种原始类型,使用 typeof 运算符检查) 2.2 null 与 Object 3. 原始值 3.1 原始值基本概念 3.2 各类型说明 1. 什么叫动态类型 JavaScript 是一种弱类型或者说动态语言. 我们不用提前声明变量的类型,在程序运行过程中,类型会被自动确定. 这也意味着你可以使用同一个变量保存不同类型的数据 let a; // 初始不给任何类型 a = 11; // a此时是number类型 a = "二大爷"; // a

  • 一文带你了解CNN(卷积神经网络)

    目录 前言 一.CNN解决了什么问题? 二.CNN网络的结构 2.1 卷积层 - 提取特征 卷积运算 权重共享 稀疏连接 总结:标准的卷积操作 卷积的意义 1x1卷积的重大意义 2.2 激活函数 2.3 池化层(下采样) - 数据降维,避免过拟合 2.4 全连接层 - 分类,输出结果 三.Pytorch实现LeNet网络 3.1 模型定义 3.2 模型训练(使用GPU训练) 3.3 训练和评估模型 前言   在学计算机视觉的这段时间里整理了不少的笔记,想着就把这些笔记再重新整理出来,然后写成Bl

  • 一文带你看懂Android Application启动流程是怎样的

    基于Android11-API30 总览 获取applicationThread,AMS这两个Binder2.attach时,将获取applicationThread对象也传递到AMS进程,请求远程调用通知AMS应用进程想要创建Application,此时AMS为服务端 AMS收到消息,请求调用applicationThread的远程接口,此时AMS为客户端 applicationThread收到AMS的请求,通过Handler发起创建Application的处理任务,后面就没有远程接口调用了

  • 一文带你走进js数据类型与数据结构的世界

    目录 1. 什么叫动态类型 2. 数据类型 2.1 原始类型(6 种原始类型,使用 typeof 运算符检查) 2.2 null 与 Object 2.3 typeof 操作符重点说明 3. 原始值 3.1 原始值基本概念 3.2 各类型说明 1. 什么叫动态类型 JavaScript 是一种弱类型或者说动态语言. 我们不用提前声明变量的类型,在程序运行过程中,类型会被自动确定. 这也意味着你可以使用同一个变量保存不同类型的数据 let a; // 初始不给任何类型 a = 11; // a此时

  • 一文带你搞懂Spring响应式编程

    目录 1. 前言 1.1 常用函数式编程 1.2 Stream操作 2. Java响应式编程 带有中间处理器的响应式流 3. Reactor 3.1 Flux & Mono 3.2 Flux Mono创建与使用 4. WebFlux Spring WebFlux示例 基于注解的WebFlux 基于函数式编程的WebFlux Flux与Mono的响应式编程延迟示例 总结 哈喽,大家好,我是指北君. 相信响应式编程经常会在各种地方被提到.本篇就为大家从函数式编程一直到Spring WeFlux做一次

  • 一文带你解密Python可迭代对象的排序问题

    假设有一个可迭代对象,现在想要对它内部的元素进行排序,我们一般会使用内置函数 sorted,举个例子: data = (3, 4, 1, 2, 5) print(     sorted(data) )  # [1, 2, 3, 4, 5] data = (3.14, 2, 1.75) print(     sorted(data) )  # [1.75, 2, 3.14] data = ["satori", "koishi", "marisa"]

随机推荐