zoukankan      html  css  js  c++  java
  • 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();
            }
        }
  • 相关阅读:
    输入重定向,输出重定向,管道相关内容及实现方法
    真正理解linux的inode?
    5分钟让你明白“软链接”和“硬链接”的区别
    linux umask使用详解
    浅谈Linux下mv和cp命令的区别
    Echarts中窗口自适应
    Echarts中series循环添加数据
    Echarts中tooltip格式化数据
    解决MySQL远程连接很慢问题
    解决Linux(CentOS) mysql命令:-bash: mysql: command not found
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10227341.html
Copyright © 2011-2022 走看看