/// <summary> /// 其他混合锁 /// </summary> internal sealed class AnotherHybridLock : IDisposable { //由基元用户模式构造(Interlocked的方法)使用 private int _waiters = 0; //AutoResetEvent 是基元内核模式构造 private AutoResetEvent _waiterLock = new AutoResetEvent(false); //这个字段控制自旋,希望提升性能 private int _spinCount = 4000; //随便选择的一个计数 //这些字段指出哪个线程拥有锁,以及拥有了它多少次 private int _owingThreadId = 0, _recursion = 0; public void Enter() { //如果调用线程已经拥有锁,递增递归计数并返回 int threadId = Thread.CurrentThread.ManagedThreadId; if (threadId == _owingThreadId) { _recursion++; return; } //调用的线程不再拥有锁,尝试获取它 SpinWait spinwait = new SpinWait(); for (int i = 0; i < _spinCount; i++) { //如果锁可以自由使用了,这个线程就获得它:设置一些状态并返回 if (Interlocked.CompareExchange(ref _waiters, 1, 0) == 0) goto GotLock; //黑科技:给其他线程运行的机会,希望锁会被释放 spinwait.SpinOnce(); } //自旋结束,锁仍未获得,再试一次 if (Interlocked.Increment(ref _waiters) > 1) { //仍然是竞态条件,这个线程必须阻塞 _waiterLock.WaitOne(); //等待锁:性能有损失 //等待这个线程醒来时,它拥有锁:设置一些状态并返回 } GotLock: //一个线程获得锁时,我们记录它的ID,并指出线程拥有锁一次 _owingThreadId = threadId; _recursion = 1; } public void Leave() { //如果调用线程不再拥有锁,表明存在bug int threadId = Thread.CurrentThread.ManagedThreadId; if (threadId != _owingThreadId) throw new SynchronizationLockException("Lock not owned by calling thread"); //递减递归计数。如果这个线程仍然拥有锁,那么直接返回 if (--_recursion > 0) return; _owingThreadId = 0; //现在没有线程拥有锁 //如果没有其他线程在等待,直接返回 if (Interlocked.Decrement(ref _waiters) == 0) return; //有其他线程正在阻塞,唤醒其中一个 _waiterLock.Set(); //这里产生较大的性能影响 } public void Dispose() { _waiterLock.Dispose(); } }