锁机制

对共享资源锁定,防止多线程共享中间数据问题

并行-->串行

 

  • 用户模式锁:通过一些CPU指令或死循环,达到线程等待或休眠
  • 内核模式锁:调用Win32底层代码(thread.sleep),实现Thread操作
  • 混合模式锁:用户模式+内核模式

 

用户模式锁

  1. 易变结构 volatile
    防止编译器、CPU优化;读取数据都在内存中读取
  2. 互锁结构 Interlocked
    只能做一些简单类型的计算
    Interlocked.Add 增加
    Interlocked.Increment 自增
    Interlocked.Decrement 自减
    Interlocked.Exchange 赋值
    Interlocked.CompareExchange 比较赋值
  3. spinLock 特殊的逻辑让Thread在用户模式自旋,欺骗CPU当前线程正在运行(其实是做一些无效操作占用CPU)

 内核模式锁

  1. 事件锁
    AutoResetEvent
    ManualResetEvent
  2. 信号量
    Semaphore
  3. 互斥锁
    Mutex

    以上三种锁都继承WaitHandle,底层都是通过SafeWaitHandle来对win32 Api的引用

ReadWriteLock

ReaderWriterLock.AcquireReaderLock
ReaderWriterLock.AcquireWriterLock
ReaderWriterLock.ReleaseReaderLock
ReaderWriterLock.ReleaseWriterLock

长时间读可能导致写超时,长时间的写也可能导致读超时

CountdownEvent

限制线程数的一个机制

Reset: 重置当前的threadcount上线

Signal:将当前的threadcount--操作

Wait: 相当于我们的Task.WaitAll

Monitor / Lock

Enter中添加的对象,相当于把对象的同步块索引和CLR的同步块数组了关联。(同步块索引默认为-1)

Exit中释放的资源,相当于把对象的同步快索引和CLR的同步块数组进行了解绑。

混合锁

  1. ManualResetEventSlim
    支持取消;通过用户模式锁和内核模式锁优化,不直接使用内核模式所,提升性能
  2. ReaderWriterLockSlim
  3. ReaderWriterLockSlim

Thread.Sleep(1) 休眠1ms

Thread.Sleep(0) 放弃当前时间片,让同优先级或更高优先级线程获得时间片

Thread.Yield() 放弃当前时间片,让更低优先级线程获得时间片,当其它线程时间片结束,本线程再度唤醒

等待时间 Yeild < Sleep(0) < Yeild(1)

Thread.SpinWait() 只是让CPU去执行一段没有用的代码。当时间结束之后能马上继续执行,而不是重新参与CPU的竞争

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

在内旋的情况下,使用大量的Sleep(0),Sleep(1),Yield等语法

线程安全集合

  1. ConcurrentBag
  2. ConcurrentDictionary
  3. ConcurrentQueue
  4. ConcurrentStack 链表实现的
posted @ 2019-10-15 20:11  vvf  阅读(149)  评论(0编辑  收藏  举报