时间锁,信号量,互斥锁,读写锁,互锁,易变构造

  1. 分类

    1. 用户模式锁,通过一些cpu指令或者一个死循环,达到Thread等待或休眠

      1. 易变结构:一个线程读,一个写

        Thread.MemoryBarrier , Thread.VolatileRead,volatile关键字

        public static volatile bool isStop = false;
      2. 互锁结构 Interlocked
        Increment:自增操作
        Decrement:自减操作
        Add: 增加指定的值
        Exchange: 赋值
        CompareExchange: 比较赋值

      3. 旋转锁:SpinLock
        Enter 获取锁
        Exit 释放锁

    2. 内核模式锁,调用win32底层代码

      1. 自动事件锁:AutoResetEvent true:表示终止状态 false:表示非终止

        static AutoResetEvent areLock = new AutoResetEvent(false);
        static void Main(string[] args)
        {
            areLock.WaitOne(); //塞一张火车票到闸机中,因为此时有票在闸机,所以我只能等待 
            Console.WriteLine("火车票检验通过,可以通行");
            areLock.Set();   //从闸机中取走火车票
        }
      2. 手动事件锁:ManualResetEvent

        static ManualResetEvent mreLock = new ManualResetEvent(false);
        mreLock.Set();
        mreLock.WaitOne();
        //doSomething
      3. Semaphore 限制可同时访问某资源的线程数

        static Semaphore seLock = new Semaphore(1, 10);
        seLock.WaitOne();
        //doSomething
         seLock.Release();
      4. Mutex互斥锁

        static Mutex mutex = new Mutex();
        mutex.WaitOne();
        //doSomething
        mutex.ReleaseMutex();

      继承自WaitHandle,都有一个WaitOne方法,底层都是通过SafeWaitHandle来对win32api的一个引用

      1. ReaderWriterLock 单个写线程和多个读线程的锁。

        static ReaderWriterLock rwlock = new ReaderWriterLock();
        rwlock.AcquireReaderLock(int.MaxValue);//指定超时时间的获取读线程锁
        //读
        rwlock.ReleaseReaderLock();
        
        rwlock.AcquireWriterLock(int.MaxValue);//指定超时时间的获取写线程锁
        //写
        rwlock.ReleaseWriterLock();
      2. CountdownEvent 限制线程数

        static CountdownEvent cdeLock = new CountdownEvent(10);//指定10个线程
        cdeLock.Signal();//注册信号,线程数减一
        cdeLock.Wait();//相当于Task.WaitAll
        cdeLock.Reset(2);//重置线程数
    3. 混合锁,用户模式+内核模式,*slim

      先在用户模式下内旋,如果超过一定的阈值,会切换到内核锁

      在内旋的情况下,我们会看到大量的Sleep(0),Sleep(1),Yield等语法

      1. SemaphoreSlim
      2. ManualResetEventSlim
      3. ReaderWriterLockSlim
      4. ManualResetEventSlim
    4. lock 监视锁 (语法糖) Monitor

      Enter 锁住某一个资源,相当于把对象的同步块索引和CLR的同步块数组了关联。

      Exit 退出某一个资源,相当于把对象的同步快索引和CLR的同步块数组进行了解绑。

      注意点:

      锁住的资源要让线程都可以访问到

      锁住的资源不要使用值类型(值类型传递是拷贝副本)

  2. 为什么要用锁

    多个线程对一个“共享资源”进行操作的时候,容易出现共享资源混乱