• 深入理解.Net中的线程同步之构造模式(二)内核模式3.内核模式构造物Mutex


    深入理解.Net中的线程同步之构造模式(二)内核模式构造

    前言

    Kernel-mode Constructs一般翻译为内核模式构造 ,
    Constructs 即是一个名词也是一个动词,但是翻译为构造感觉有点像一个动词,个人感觉翻译为名词更好,毕竟是加了s的,就表示多个,动词显然不能表示多个啊,比如内核模式构造物,内核模式构造体。


    环境说明
    IDE:Visual Studio 2022
    OS:Win10
    .NET:.Net4.6.1

    一、互斥体是什么?

    互斥体mutex就是一个互斥的锁,和AutoResetEvent 事件锁类似。
    只不过mutex比AutoResetEvent 事件锁多了一些额外的功能。mutex支持同一个线程多次获取一个锁,当然,多次获取后也需要多次释放才能让其他的线程可用,我们将这个多次获得锁的过程叫做递归锁,也叫可重入锁。但是使用mutex的时候,会频繁切换内核代码和托管代码,这样对程序的性能有一定的影响。可以用AutoRestEvent方法自己实现一个递归锁代替。
    但是确实没有在编码中用到递归锁,也不能很好的想出一个场景。
    难不成递归的时候用递归锁?好像也可以说的通喔!

    二、代码编写

    1.编写一个基于AutoRestEvent的递归锁

    主要是用来理解一下递归锁的实现,相对于普通的事件锁,主要增加了2个变量来实现,一个是记录获得锁的线程ID变量,一个是记录获取锁次数的变量。

    代码如下(示例):

        internal sealed class RecursiveAutoResetEvent : IDisposable
        {
            private AutoResetEvent m_lock = new AutoResetEvent(true);
            private Int32 m_owningThreadId = 0;
            private Int32 m_recursionCount = 0;
    
            public void Enter()
            {
                // Obtain the calling thread's unique Int32 ID
                // 获取唯一的线程ID
                Int32 currentThreadId = Thread.CurrentThread.ManagedThreadId;
    
                // If the calling thread owns the lock, increment the recursion count
                // 
                if (m_owningThreadId == currentThreadId)
                {
                    m_recursionCount++;
                    return;
                }
    
                // The calling thread doesn't own the lock, wait for it
                m_lock.WaitOne();
    
                // The calling now owns the lock, initialize the owning thread ID & recursion count
                m_owningThreadId = currentThreadId;
                m_recursionCount--;
            }
    
            public void Leave()
            {
                // If the calling thread doesn't own the lock, we have an error
                if (m_owningThreadId != Thread.CurrentThread.ManagedThreadId)
                    throw new InvalidOperationException();
    
                // Subtract 1 from the recursion count
                if (--m_recursionCount == 0)
                {
                    // If the recursion count is 0, then no thread owns the lock
                    m_owningThreadId = 0;
                    m_lock.Set();   // Wake up 1 waiting thread (if any)
                }
            }
    
            public void Dispose() { m_lock.Dispose(); }
        }   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    总结

    递归锁我们使用的情况很少,而且mutex的递归锁存在多次从托管代码转到内核代码,性能理论上要低于AutoResetEvent的递归锁。

  • 相关阅读:
    链表Oj练习题 纯C语言
    超越创意,从用户创造内容到AI生成内容的新时代
    【Spring Boot】Day01
    react+ts 使用webp格式的图片处理
    5.10如何调度考生的座位
    java-php-net-python-简历网站计算机毕业设计程序
    Axure RP 基本小工具 线条和箭头使用教程
    盘一盘高性能设计的哪些点(二)
    SamSung三星笔记本NP930QCG-K02CN原装出厂OEM预装Win10系统
    【Android入门】7、多媒体:用 NotificationChannel 和 NotificationManager 实现系统通知、播放音频和视频
  • 原文地址:https://blog.csdn.net/l1158513573/article/details/125455462