本文主要讲解.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 Core底层入门总结内容

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

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

个人微信

一文带你了解.Net互斥锁的更多相关文章

  1. 一文带你剖析LiteOS互斥锁Mutex源代码

    摘要:多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用.LiteOS使用互斥锁来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占 ...

  2. 图解AQS的设计与实现,手摸手带你实现一把互斥锁!

    AQS是并发编程中非常重要的概念,它是juc包下的许多并发工具类,如CountdownLatch,CyclicBarrier,Semaphore 和锁, 如ReentrantLock, ReaderW ...

  3. 一文带你了解.Net自旋锁

    本文主要讲解.Net基于Thread实现自旋锁的三种方式 基于Thread.SpinWait实现自旋锁 实现原理:基于Test--And--Set原子操作实现 使用一个数据表示当前锁是否已经被获取 0 ...

  4. 一文带你.Net混合锁和lock语句

    本文主要讲解.Net基于Monitor.Enter和lock实现互斥锁 Monitor.Enter实现 相比前面的锁来说,混合锁的性能更高,任何引用类型的对象都可以做为锁对象,不需要事先创建指定类型的 ...

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

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

  6. 互斥锁pthread_mutex_t的使用(转载)

    1. 互斥锁创建        有两种方法创建互斥锁,静态方式和动态方式.POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下: pthread_mut ...

  7. pthread_mutex_init & 互斥锁pthread_mutex_t的使用

    pthread_mutex_init l         头文件: #include <pthread.h> l         函数原型: int pthread_mutex_init( ...

  8. PHP程序中的文件锁、互斥锁、读写锁使用技巧解析

    文件锁全名叫 advisory file lock, 书中有提及. 这类锁比较常见,例如 mysql, php-fpm 启动之后都会有一个pid文件记录了进程id,这个文件就是文件锁. 这个锁可以防止 ...

  9. Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

    (1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...

随机推荐

  1. Jenkins反序列化漏洞复现

    Jenkins Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. Jenkins功能包括: 持 ...

  2. Docker仓库-Docker Hub

    Docker Hub Docker官方维护了一个公共仓库Docker Hub,其中已经包括了数量上百万的镜像,大部分需求都可以通过在Docker Hub 中直接下载镜像来实现. 注册: https:/ ...

  3. 学习Canvas绘图与动画基础 为多边形着色(三)

    1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="U ...

  4. PHP基础-常用的数组相关处理函数

    一 数组键/值操作有关的函数 1. array_values()//获取数组中所有的值 $lamp=array("os"=>"linux", " ...

  5. JVM什么叫安全检测点

    [deerhang] 在JVM的垃圾回收阶段,GC线程首先要进行对象的可达性分析.为了避免多线程对可达性分析的影响引出了安全点检测的概念 当GC线程进行GC前,需要等待其他线程进入安全点.例如JVM调 ...

  6. Linux 中如何使用 IP 命令

    老版本的 Linux 中都是使用 ifconfig 命令检查和配置网络接口,但是该命令目前已经没有维护了,取而代之的是 ip 命令 ip 命令和 ifconfig 命令很相似,但是 相比起来,ip命令 ...

  7. 关于Annotation注解的理解

    在编Java程序的时候,我们经常会碰到annotation.比如:@Override 我们在子类继承父类的时候,会经常用到这个annotation.它告诉编译器这个方法是override父类的方法的. ...

  8. [基本运算符、流程控制之if判断、与用户交互、深浅拷贝]

    [基本运算符.流程控制之if判断.与用户交互] 基本运算符 1.算数运算符 python支持的算术运算符与数学上计算的符号使用是一致的 salary = 3.3 res = salary * 12 p ...

  9. 『动善时』JMeter基础 — 20、JMeter配置元件【HTTP Cookie管理器】详细介绍

    目录 1.HTTP Cookie管理器介绍 2.HTTP Cookie管理器界面详解 3.JMeter中对Cookie的管理 (1)Cookie的存储 (2)Cookie的管理策略 4.补充:Cook ...

  10. 查阅日志文件:有时候报错信息只是给出了问题的表面现象,要想更深入的了解问题,必须查看相应的日志文件,而日志文件又分为系统日志文件(/var/log)和应用的日志文件,结合这两个日志文件,一般就能定位问题所在。

    作为一名合格的 Linux 运维工程师,一定要有一套清晰.明确的解决故障思路,当问题出现时,才能迅速定位.解决问题,这里给出一个处理问题的一般思路: 重视报错提示信息:每个错误的出现,都是给出错误提示 ...