锁机制
对共享资源锁定,防止多线程共享中间数据问题
并行-->串行
- 用户模式锁:通过一些CPU指令或死循环,达到线程等待或休眠
- 内核模式锁:调用Win32底层代码(thread.sleep),实现Thread操作
- 混合模式锁:用户模式+内核模式
用户模式锁
- 易变结构 volatile
防止编译器、CPU优化;读取数据都在内存中读取 - 互锁结构 Interlocked
只能做一些简单类型的计算
Interlocked.Add 增加
Interlocked.Increment 自增
Interlocked.Decrement 自减
Interlocked.Exchange 赋值
Interlocked.CompareExchange 比较赋值 - spinLock 特殊的逻辑让Thread在用户模式自旋,欺骗CPU当前线程正在运行(其实是做一些无效操作占用CPU)
内核模式锁
- 事件锁
AutoResetEvent
ManualResetEvent - 信号量
Semaphore - 互斥锁
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的同步块数组进行了解绑。
混合锁
- ManualResetEventSlim
支持取消;通过用户模式锁和内核模式锁优化,不直接使用内核模式所,提升性能 - ReaderWriterLockSlim
- ReaderWriterLockSlim
Thread.Sleep(1) 休眠1ms
Thread.Sleep(0) 放弃当前时间片,让同优先级或更高优先级线程获得时间片
Thread.Yield() 放弃当前时间片,让更低优先级线程获得时间片,当其它线程时间片结束,本线程再度唤醒
等待时间 Yeild < Sleep(0) < Yeild(1)
Thread.SpinWait() 只是让CPU去执行一段没有用的代码。当时间结束之后能马上继续执行,而不是重新参与CPU的竞争
先在用户模式下内旋,如果超过一定的阈值,会切换到内核锁
在内旋的情况下,使用大量的Sleep(0),Sleep(1),Yield等语法
线程安全集合
- ConcurrentBag
- ConcurrentDictionary
- ConcurrentQueue
- ConcurrentStack 链表实现的