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(); } } } } }