• 30.2 自旋、线程所有权和递归


        /// <summary>
        /// 其他混合锁
        /// </summary>
        internal sealed class AnotherHybridLock : IDisposable
        {
            //由基元用户模式构造(Interlocked的方法)使用
            private int _waiters = 0;
    
            //AutoResetEvent 是基元内核模式构造
            private AutoResetEvent _waiterLock = new AutoResetEvent(false);
    
            //这个字段控制自旋,希望提升性能
            private int _spinCount = 4000;      //随便选择的一个计数
    
            //这些字段指出哪个线程拥有锁,以及拥有了它多少次
            private int _owingThreadId = 0, _recursion = 0;
    
            public void Enter()
            {
                //如果调用线程已经拥有锁,递增递归计数并返回
                int threadId = Thread.CurrentThread.ManagedThreadId;
                if (threadId == _owingThreadId)
                {
                    _recursion++;
                    return;
                }
    
                //调用的线程不再拥有锁,尝试获取它
                SpinWait spinwait = new SpinWait();
                for (int i = 0; i < _spinCount; i++)
                {
                    //如果锁可以自由使用了,这个线程就获得它:设置一些状态并返回
                    if (Interlocked.CompareExchange(ref _waiters, 1, 0) == 0)
                        goto GotLock;
    
                    //黑科技:给其他线程运行的机会,希望锁会被释放
                    spinwait.SpinOnce();
                }
    
                //自旋结束,锁仍未获得,再试一次
                if (Interlocked.Increment(ref _waiters) > 1)
                {
                    //仍然是竞态条件,这个线程必须阻塞
                    _waiterLock.WaitOne();  //等待锁:性能有损失
                    //等待这个线程醒来时,它拥有锁:设置一些状态并返回
                }
    
                GotLock:
                //一个线程获得锁时,我们记录它的ID,并指出线程拥有锁一次
                _owingThreadId = threadId;
                _recursion = 1;
            }
    
            public void Leave()
            {
                //如果调用线程不再拥有锁,表明存在bug
                int threadId = Thread.CurrentThread.ManagedThreadId;
                if (threadId != _owingThreadId)
                    throw new SynchronizationLockException("Lock not owned by calling thread");
    
                //递减递归计数。如果这个线程仍然拥有锁,那么直接返回
                if (--_recursion > 0)
                    return;
    
                _owingThreadId = 0; //现在没有线程拥有锁
    
                //如果没有其他线程在等待,直接返回
                if (Interlocked.Decrement(ref _waiters) == 0)
                    return;
    
                //有其他线程正在阻塞,唤醒其中一个
                _waiterLock.Set();      //这里产生较大的性能影响
            }
    
            public void Dispose()
            {
                _waiterLock.Dispose();
            }
        }
  • 相关阅读:
    Apache虚拟主机配置
    【笔记】php常用函数
    【笔记】linux x86漏洞利用
    【笔记】ubuntu如何切换到root用户&&linux如何关闭各种保护
    【实验吧】登陆一下好吗???
    渗透相关website
    【实验吧】Reverse400
    ajax+jquery+ashx如何实现上传文件
    使用Jquery解析Json基础知识
    C#中把Datatable转换为Json的5个代码实例
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10227341.html
Copyright © 2020-2023  润新知