zoukankan      html  css  js  c++  java
  • 原子操作、自旋锁

       private static int a = 0;
            static void Main(string[] args)
            {
                // 原子操作
                var b = 0;
                b = Interlocked.Increment(ref a); // 自增1
    
                b = Interlocked.Decrement(ref a);// 自减
    
                b = Interlocked.Add(ref a,  b); // 返回a 加b的值
    
                Interlocked.Exchange(ref a, 1); // 返回交换后的值,
    
                Interlocked.CompareExchange(ref a, 2, 0);  // 变量a的值如果等于0,则将2 赋值给a ,并且然后返回原始值(修改之前的值)
    

      

    自旋锁:

       线程会不断的循环获取锁,直到锁被释放。  不公平的锁,没办法保证等待最长时间的线程获取锁,假如有8个线程,都在不断循环获取锁,总有线程‘’点子背‘’,获取不到锁(线程饥饿)

      优点:自旋锁 不会使线程的状态切换,减小上下文的切换,上下文的切换 会消耗性能

      public static class Sample
        {
            private static int _lock = 0;
            private static int _CounterA = 0;
            private static int _Counterb = 0;
    
            private static SpinLock _locker = new SpinLock();
    
            public static void IncrementCounter()
            {
                var spinwait = new SpinWait();
                while (Interlocked.Exchange(ref _lock, 1) != 0)
                {
                    // 汇编指令,pause
                    Thread.SpinWait(1);
                    // 或者
    
                    spinwait.SpinOnce();
                    // 一定次数内,核心数大于1。会调用   Thread.SpinWait
                    // 超过一定的次数,核心数等于1,会交替调用
                    // 【thread.sleep(0)[windows中的sleep函数,实际上调用sleepex的一个系统函数]和thread.yied[他是调用一个叫switchtothread的函数],
                    // 前者在整个核心中切换,后者只在自己核心切换,前者赋值0的意义是立刻放在待执行的队列里】
                    // 交替使用告诉操作系统切换到其他线程
                    //在超过一定的次数,thread.sleep(1) 会休眠1毫秒,减少性能消耗
                }
    
                //锁保护区
                {
                    _CounterA++;
                    _Counterb++;
                }
                // 释放锁
                Interlocked.Exchange(ref _lock, 0);
    
    
                // 以下方式可替换上面,直接使用封装好的类,直接实现了自旋锁
                {
                    var lockToken = false;
                    try
                    {
                        _locker.Enter(ref lockToken);
                        // 锁保护区
                        {
                            _CounterA++;
                            _Counterb++;
                        }
                    }
                    finally
                    {
                        // 释放锁
                        if (lockToken)
                        {
                            _locker.Exit();
                        }
                    }
                }
    
    
            }
        }
    

      

  • 相关阅读:
    Auto-Test 要点纪录(一)
    终端应用变身文件 MD5/SHA1 校验工具
    MD5 algorithm in Objective C
    iphone开发-SQLite数据库使用
    【React】354- 一文吃透 React 事件机制原理
    【Web技术】353- CDN 科普
    【CSS】352- 有趣的CSS弹跳动画
    【Vuejs】351- 带你解析vue2.0的diff算法
    【每周小回顾】7- 一起回顾上周精彩内容
    【Vuejs】350- 学习 Vue 源码的必要知识储备
  • 原文地址:https://www.cnblogs.com/hnzheng/p/13407617.html
Copyright © 2011-2022 走看看