摘要:做线程同步的时候一般都用Monitor对象或者lock关键字,其实好多场景是对资源读多写少,这时应该使用读写锁,而.net自带的ReaderWriterLock的性能有问题,于是我把.net 3.0的ReaderWriterLockSlim类给提取出来了。
关于ReaderWriterLock和ReaderWriterLockSlim的对比,参考如下链接:并发数据结构 : .NET Framework 中提供的读写锁
当然直接引用.net 3.0的System.Core.dll也可以使用,但那样有些火箭穿蚊子,另外对ReaderWriterLockSlim类的实现原理没仔细看,但我没做重要的改动,就把抛异常的时候从资源文件里读异常的本地化Message的地方换了一个方法。这个类的性能比.net 2.0的好很多,是用Thread.SpinWait和Interlocked.CompareExchange等实现的,代码写的比较诡异,有好多没用到的字段,还有一些从来没有初始化的字段,不知道到底有没有用都,比较汗,把代码贴出来,如下
using System;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Threading;

namespace System.Threading


{

LockRecursionPolicy#region LockRecursionPolicy
public enum LockRecursionPolicy

{
NoRecursion,
SupportsRecursion
}
#endregion


RecursiveCounts#region RecursiveCounts
internal class RecursiveCounts

{
// Fields
public int upgradecount;
public int writercount;
}
#endregion


ReaderWriterCount#region ReaderWriterCount
internal class ReaderWriterCount

{
// Fields
public ReaderWriterCount next;
public RecursiveCounts rc;
public int readercount;
public int threadid = -1;

// Methods
public ReaderWriterCount(bool fIsReentrant)

{
if (fIsReentrant)

{
rc = new RecursiveCounts();
}
}
}
#endregion


LockRecursionException#region LockRecursionException
[Serializable, HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
public class LockRecursionException : Exception

{
// Methods
public LockRecursionException()

{
}

public LockRecursionException(string message)
: base(message)

{
}

protected LockRecursionException(SerializationInfo info, StreamingContext context)
: base(info, context)

{
}

public LockRecursionException(string message, Exception innerException)
: base(message, innerException)

{
}
}
#endregion


ReaderWriterLockSlim#region ReaderWriterLockSlim
[HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true),
HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
public class ReaderWriterLockSlim : IDisposable

{

private fidlds#region private fidlds
private const int hashTableSize = 0xff;
private const int LockSleep0Count = 5;
private const int LockSpinCount = 10;
private const int LockSpinCycles = 20;
private const uint MAX_READER = 0xffffffe;
private const int MaxSpinCount = 20;
private const uint READER_MASK = 0xfffffff;
private const uint WAITING_UPGRADER = 0x20000000;
private const uint WAITING_WRITERS = 0x40000000;
private const uint WRITER_HELD = 0x80000000;
private readonly bool fIsReentrant;
private bool fDisposed;
private bool fNoWaiters;
private bool fUpgradeThreadHoldingRead;
private int myLock;
private uint numReadWaiters;
private uint numUpgradeWaiters;
private uint numWriteUpgradeWaiters;
private uint numWriteWaiters;
private uint owners;
private EventWaitHandle readEvent;
private ReaderWriterCount[] rwc;
private EventWaitHandle upgradeEvent;
private int upgradeLockOwnerId;
private EventWaitHandle waitUpgradeEvent;
private EventWaitHandle writeEvent;
private int writeLockOwnerId;
#endregion


public contructs#region public contructs
public ReaderWriterLockSlim()
: this(LockRecursionPolicy.NoRecursion)

{
}

public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy)

{
if (recursionPolicy == LockRecursionPolicy.SupportsRecursion)

{
fIsReentrant = true;
}
InitializeThreadCounts();
}
#endregion


public properties#region public properties
public int CurrentReadCount

{
get

{
int numReaders = (int)GetNumReaders();
if (upgradeLockOwnerId != -1)

{
return (numReaders - 1);
}
return numReaders;
}
}

public bool IsReadLockHeld

{

get
{ return (RecursiveReadCount > 0); }
}

public bool IsUpgradeableReadLockHeld

{

get
{ return (RecursiveUpgradeCount > 0); }
}

public bool IsWriteLockHeld

{

get
{ return (RecursiveWriteCount > 0); }
}

public LockRecursionPolicy RecursionPolicy

{
get

{
if (fIsReentrant)

{
return LockRecursionPolicy.SupportsRecursion;
}
return LockRecursionPolicy.NoRecursion;
}
}

public int RecursiveReadCount

{
get

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
int readercount = 0;
EnterMyLock();
ReaderWriterCount threadRWCount = GetThreadRWCount(managedThreadId, true);
if (threadRWCount != null)

{
readercount = threadRWCount.readercount;
}
ExitMyLock();
return readercount;
}
}

public int RecursiveUpgradeCount

{
get

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (fIsReentrant)

{
int upgradecount = 0;
EnterMyLock();
ReaderWriterCount threadRWCount = GetThreadRWCount(managedThreadId, true);
if (threadRWCount != null)

{
upgradecount = threadRWCount.rc.upgradecount;
}
ExitMyLock();
return upgradecount;
}
if (managedThreadId == upgradeLockOwnerId)

{
return 1;
}
return 0;
}
}

public int RecursiveWriteCount

{
get

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
int writercount = 0;
if (fIsReentrant)

{
EnterMyLock();
ReaderWriterCount threadRWCount = GetThreadRWCount(managedThreadId, true);
if (threadRWCount != null)

{
writercount = threadRWCount.rc.writercount;
}
ExitMyLock();
return writercount;
}
if (managedThreadId == writeLockOwnerId)

{
return 1;
}
return 0;
}
}

public int WaitingReadCount

{

get
{ return (int)numReadWaiters; }
}

public int WaitingUpgradeCount

{

get
{ return (int)numUpgradeWaiters; }
}

public int WaitingWriteCount

{

get
{ return (int)numWriteWaiters; }
}
#endregion


IDisposable Members#region IDisposable Members

public void Dispose()

{
Dispose(true);
}
private void Dispose(bool disposing)

{
if (disposing)

{
if (fDisposed)

{
throw new ObjectDisposedException(null);
}
if (((WaitingReadCount > 0) || (WaitingUpgradeCount > 0)) || (WaitingWriteCount > 0))

{
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_IncorrectDispose"));
}
if ((IsReadLockHeld || IsUpgradeableReadLockHeld) || IsWriteLockHeld)

{
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_IncorrectDispose"));
}
if (writeEvent != null)

{
writeEvent.Close();
writeEvent = null;
}
if (readEvent != null)

{
readEvent.Close();
readEvent = null;
}
if (upgradeEvent != null)

{
upgradeEvent.Close();
upgradeEvent = null;
}
if (waitUpgradeEvent != null)

{
waitUpgradeEvent.Close();
waitUpgradeEvent = null;
}
fDisposed = true;
}
}

#endregion


private methods#region private methods
private string GetStringFromResource(string key)

{
return key;
}

private void ClearUpgraderWaiting()

{
owners &= 0xdfffffff;
}

private void ClearWriterAcquired()

{
owners &= 0x7fffffff;
}

private void ClearWritersWaiting()

{
owners &= 0xbfffffff;
}


private void EnterMyLock()

{
if (Interlocked.CompareExchange(ref myLock, 1, 0) != 0)

{
EnterMyLockSpin();
}
}

private void EnterMyLockSpin()

{
int processorCount = Environment.ProcessorCount;
int num2 = 0;
while (true)

{
if ((num2 < 10) && (processorCount > 1))

{
Thread.SpinWait(20 * (num2 + 1));
}
else if (num2 < 15)

{
Thread.Sleep(0);
}
else

{
Thread.Sleep(1);
}
if ((myLock == 0) && (Interlocked.CompareExchange(ref myLock, 1, 0) == 0))

{
return;
}
num2++;
}
}



private void ExitAndWakeUpAppropriateWaiters()

{
if (fNoWaiters)

{
ExitMyLock();
}
else

{
ExitAndWakeUpAppropriateWaitersPreferringWriters();
}
}

private void ExitAndWakeUpAppropriateWaitersPreferringWriters()

{
bool flag = false;
bool flag2 = false;
uint numReaders = GetNumReaders();
if ((fIsReentrant && (numWriteUpgradeWaiters > 0)) && (fUpgradeThreadHoldingRead && (numReaders == 2)))

{
ExitMyLock();
waitUpgradeEvent.Set();
}
else if ((numReaders == 1) && (numWriteUpgradeWaiters > 0))

{
ExitMyLock();
waitUpgradeEvent.Set();
}
else if ((numReaders == 0) && (numWriteWaiters > 0))

{
ExitMyLock();
writeEvent.Set();
}
else if (numReaders >= 0)

{
if ((numReadWaiters == 0) && (numUpgradeWaiters == 0))

{
ExitMyLock();
}
else

{
if (numReadWaiters != 0)

{
flag2 = true;
}
if ((numUpgradeWaiters != 0) && (upgradeLockOwnerId == -1))

{
flag = true;
}
ExitMyLock();
if (flag2)

{
readEvent.Set();
}
if (flag)

{
upgradeEvent.Set();
}
}
}
else

{
ExitMyLock();
}
}
private uint GetNumReaders()

{
return (owners & 0xfffffff);
}

private ReaderWriterCount GetThreadRWCount(int id, bool DontAllocate)

{
int index = id & 0xff;
ReaderWriterCount count = null;
if (rwc[index].threadid == id)

{
return rwc[index];
}
if (IsRWEntryEmpty(rwc[index]) && !DontAllocate)

{
if (rwc[index].next == null)

{
rwc[index].threadid = id;
return rwc[index];
}
count = rwc[index];
}
ReaderWriterCount next = rwc[index].next;
while (next != null)

{
if (next.threadid == id)

{
return next;
}
if ((count == null) && IsRWEntryEmpty(next))

{
count = next;
}
next = next.next;
}
if (DontAllocate)

{
return null;
}
if (count == null)

{
next = new ReaderWriterCount(fIsReentrant);
next.threadid = id;
next.next = rwc[index].next;
rwc[index].next = next;
return next;
}
count.threadid = id;
return count;
}

private void InitializeThreadCounts()

{
rwc = new ReaderWriterCount[0x100];
for (int i = 0; i < rwc.Length; i++)

{
rwc[i] = new ReaderWriterCount(fIsReentrant);
}
upgradeLockOwnerId = -1;
writeLockOwnerId = -1;
}

private static bool IsRWEntryEmpty(ReaderWriterCount rwc)

{
return ((rwc.threadid == -1) ||
(((rwc.readercount == 0) && (rwc.rc == null)) ||
(((rwc.readercount == 0) && (rwc.rc.writercount == 0)) && (rwc.rc.upgradecount == 0))));
}

private static bool IsRwHashEntryChanged(ReaderWriterCount lrwc, int id)

{
return (lrwc.threadid != id);
}

private bool IsWriterAcquired()

{
return ((owners & 0xbfffffff) == 0);
}

private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent)

{
EventWaitHandle handle;
ExitMyLock();
if (makeAutoResetEvent)

{
handle = new AutoResetEvent(false);
}
else

{
handle = new ManualResetEvent(false);
}
EnterMyLock();
if (waitEvent == null)

{
waitEvent = handle;
}
else

{
handle.Close();
}
}

private void SetUpgraderWaiting()

{
owners |= 0x20000000;
}

private void SetWriterAcquired()

{
owners |= 0x80000000;
}

private void SetWritersWaiting()

{
owners |= 0x40000000;
}

private static void SpinWait(int SpinCount)

{
if ((SpinCount < 5) && (Environment.ProcessorCount > 1))

{
Thread.SpinWait(20 * SpinCount);
}
else if (SpinCount < 0x11)

{
Thread.Sleep(0);
}
else

{
Thread.Sleep(1);
}
}

private void ExitMyLock()

{
myLock = 0;
}

private bool WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, int millisecondsTimeout)

{
waitEvent.Reset();
numWaiters++;
fNoWaiters = false;
if (numWriteWaiters == 1)

{
SetWritersWaiting();
}
if (numWriteUpgradeWaiters == 1)

{
SetUpgraderWaiting();
}
bool flag = false;
ExitMyLock();
try

{
flag = waitEvent.WaitOne(millisecondsTimeout, false);
}
finally

{
EnterMyLock();
numWaiters--;
if (((numWriteWaiters == 0) && (numWriteUpgradeWaiters == 0)) &&
((numUpgradeWaiters == 0) && (numReadWaiters == 0)))

{
fNoWaiters = true;
}
if (numWriteWaiters == 0)

{
ClearWritersWaiting();
}
if (numWriteUpgradeWaiters == 0)

{
ClearUpgraderWaiting();
}
if (!flag)

{
ExitMyLock();
}
}
return flag;
}
#endregion


public methods#region public methods


Enter and Exit ReadLock#region Enter and Exit ReadLock
public void EnterReadLock()

{
TryEnterReadLock(-1);
}
public void ExitReadLock()

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
ReaderWriterCount threadRWCount = null;
EnterMyLock();
threadRWCount = GetThreadRWCount(managedThreadId, true);
if (!fIsReentrant)

{
if (threadRWCount == null)

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedRead"));
}
}
else

{
if ((threadRWCount == null) || (threadRWCount.readercount < 1))

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedRead"));
}
if (threadRWCount.readercount > 1)

{
threadRWCount.readercount--;
ExitMyLock();
return;
}
if (managedThreadId == upgradeLockOwnerId)

{
fUpgradeThreadHoldingRead = false;
}
}
owners--;
threadRWCount.readercount--;
ExitAndWakeUpAppropriateWaiters();
}
#endregion


Enter and Exit WriteLock#region Enter and Exit WriteLock
public void EnterWriteLock()

{
TryEnterWriteLock(-1);
}
public void ExitWriteLock()

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (!fIsReentrant)

{
if (managedThreadId != writeLockOwnerId)

{
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedWrite"));
}
EnterMyLock();
}
else

{
EnterMyLock();
ReaderWriterCount threadRWCount = GetThreadRWCount(managedThreadId, false);
if (threadRWCount == null)

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedWrite"));
}
RecursiveCounts rc = threadRWCount.rc;
if (rc.writercount < 1)

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedWrite"));
}
rc.writercount--;
if (rc.writercount > 0)

{
ExitMyLock();
return;
}
}
ClearWriterAcquired();
writeLockOwnerId = -1;
ExitAndWakeUpAppropriateWaiters();
}
#endregion


Enter and Exit UpgradeableReadLock#region Enter and Exit UpgradeableReadLock
public void EnterUpgradeableReadLock()

{
TryEnterUpgradeableReadLock(-1);
}
public void ExitUpgradeableReadLock()

{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (!fIsReentrant)

{
if (managedThreadId != upgradeLockOwnerId)

{
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedUpgrade"));
}
EnterMyLock();
}
else

{
EnterMyLock();
ReaderWriterCount threadRWCount = GetThreadRWCount(managedThreadId, true);
if (threadRWCount == null)

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedUpgrade"));
}
RecursiveCounts rc = threadRWCount.rc;
if (rc.upgradecount < 1)

{
ExitMyLock();
throw new SynchronizationLockException(
GetStringFromResource("SynchronizationLockException_MisMatchedUpgrade"));
}
rc.upgradecount--;
if (rc.upgradecount > 0)

{
ExitMyLock();
return;
}
fUpgradeThreadHoldingRead = false;
}
owners--;
upgradeLockOwnerId = -1;
ExitAndWakeUpAppropriateWaiters();
}
#endregion


TryEnterReadLock#region TryEnterReadLock
public bool TryEnterReadLock(int millisecondsTimeout)

{
if (millisecondsTimeout < -1)

{
throw new ArgumentOutOfRangeException("millisecondsTimeout");
}
if (fDisposed)

{
throw new ObjectDisposedException(null);
}
ReaderWriterCount lrwc = null;
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (!fIsReentrant)

{
if (managedThreadId == writeLockOwnerId)

{
throw new LockRecursionException(GetStringFromResource("LockRecursionException_ReadAfterWriteNotAllowed"));
}
EnterMyLock();
lrwc = GetThreadRWCount(managedThreadId, false);
if (lrwc.readercount > 0)

{
ExitMyLock();
throw new LockRecursionException(GetStringFromResource("LockRecursionException_RecursiveReadNotAllowed"));
}
if (managedThreadId == upgradeLockOwnerId)

{
lrwc.readercount++;
owners++;
ExitMyLock();
return true;
}
}
else

{
EnterMyLock();
lrwc = GetThreadRWCount(managedThreadId, false);
if (lrwc.readercount > 0)

{
lrwc.readercount++;
ExitMyLock();
return true;
}
if (managedThreadId == upgradeLockOwnerId)

{
lrwc.readercount++;
owners++;
ExitMyLock();
fUpgradeThreadHoldingRead = true;
return true;
}
if (managedThreadId == writeLockOwnerId)

{
lrwc.readercount++;
owners++;
ExitMyLock();
return true;
}
}
bool flag = true;
int spinCount = 0;
Label_013D:
if (owners < 0xffffffe)

{
owners++;
lrwc.readercount++;
}
else

{
if (spinCount < 20)

{
ExitMyLock();
if (millisecondsTimeout == 0)

{
return false;
}
spinCount++;
SpinWait(spinCount);
EnterMyLock();
if (IsRwHashEntryChanged(lrwc, managedThreadId))

{
lrwc = GetThreadRWCount(managedThreadId, false);
}
}
else if (readEvent == null)

{
LazyCreateEvent(ref readEvent, false);
if (IsRwHashEntryChanged(lrwc, managedThreadId))

{
lrwc = GetThreadRWCount(managedThreadId, false);
}
}
else

{
flag = WaitOnEvent(readEvent, ref numReadWaiters, millisecondsTimeout);
if (!flag)

{
return false;
}
if (IsRwHashEntryChanged(lrwc, managedThreadId))

{
lrwc = GetThreadRWCount(managedThreadId, false);
}
}
goto Label_013D;
}
ExitMyLock();
return flag;
}
public bool TryEnterReadLock(TimeSpan timeout)

{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))

{
throw new ArgumentOutOfRangeException("timeout");
}
int millisecondsTimeout = (int)timeout.TotalMilliseconds;
return TryEnterReadLock(millisecondsTimeout);
}
#endregion


TryEnterWriteLock#region TryEnterWriteLock
public bool TryEnterWriteLock(int millisecondsTimeout)

{
ReaderWriterCount threadRWCount;
if (millisecondsTimeout < -1)

{
throw new ArgumentOutOfRangeException("millisecondsTimeout");
}
if (fDisposed)

{
throw new ObjectDisposedException(null);
}
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
bool flag = false;
if (!fIsReentrant)

{
if (managedThreadId == writeLockOwnerId)

{
throw new LockRecursionException(GetStringFromResource("LockRecursionException_RecursiveWriteNotAllowed"));
}
if (managedThreadId == upgradeLockOwnerId)

{
flag = true;
}
EnterMyLock();
threadRWCount = GetThreadRWCount(managedThreadId, true);
if ((threadRWCount != null) && (threadRWCount.readercount > 0))

{
ExitMyLock();
throw new LockRecursionException(GetStringFromResource("LockRecursionException_WriteAfterReadNotAllowed"));
}
}
else

{
EnterMyLock();
threadRWCount = GetThreadRWCount(managedThreadId, false);
if (managedThreadId == writeLockOwnerId)

{
threadRWCount.rc.writercount++;
ExitMyLock();
return true;
}
if (managedThreadId == upgradeLockOwnerId)

{
flag = true;
}
else if (threadRWCount.readercount > 0)

{
ExitMyLock();
throw new LockRecursionException(GetStringFromResource("LockRecursionException_WriteAfterReadNotAllowed"));
}
}
int spinCount = 0;
Label_00EC:
if (IsWriterAcquired())

{
SetWriterAcquired();
}
else

{
if (flag)

{
uint numReaders = GetNumReaders();
if (numReaders == 1)

{
SetWriterAcquired();
goto Label_01DD;
}
if ((numReaders == 2) && (threadRWCount != null))

{
if (IsRwHashEntryChanged(threadRWCount, managedThreadId))

{
threadRWCount = GetThreadRWCount(managedThreadId, false);
}
if (threadRWCount.readercount > 0)

{
SetWriterAcquired();
goto Label_01DD;
}
}
}
if (spinCount < 20)

{
ExitMyLock();
if (millisecondsTimeout == 0)

{
return false;
}
spinCount++;
SpinWait(spinCount);
EnterMyLock();
goto Label_00EC;
}
if (flag)

{
if (waitUpgradeEvent != null)

{
if (!WaitOnEvent(waitUpgradeEvent, ref numWriteUpgradeWaiters, millisecondsTimeout))

{
return false;
}
}
else

{
LazyCreateEvent(ref waitUpgradeEvent, true);
}
goto Label_00EC;
}
if (writeEvent == null)

{
LazyCreateEvent(ref writeEvent, true);
goto Label_00EC;
}
if (WaitOnEvent(writeEvent, ref numWriteWaiters, millisecondsTimeout))

{
goto Label_00EC;
}
return false;
}
Label_01DD:
if (fIsReentrant)

{
if (IsRwHashEntryChanged(threadRWCount, managedThreadId))

{
threadRWCount = GetThreadRWCount(managedThreadId, false);
}
threadRWCount.rc.writercount++;
}
ExitMyLock();
writeLockOwnerId = managedThreadId;
return true;
}
public bool TryEnterWriteLock(TimeSpan timeout)

{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))

{
throw new ArgumentOutOfRangeException("timeout");
}
int millisecondsTimeout = (int)timeout.TotalMilliseconds;
return TryEnterWriteLock(millisecondsTimeout);
}
#endregion


TryEnterUpgradeableReadLock#region TryEnterUpgradeableReadLock
public bool TryEnterUpgradeableReadLock(int millisecondsTimeout)

{
ReaderWriterCount threadRWCount;
if (millisecondsTimeout < -1)

{
throw new ArgumentOutOfRangeException("millisecondsTimeout");
}
if (fDisposed)

{
throw new ObjectDisposedException(null);
}
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (!fIsReentrant)

{
if (managedThreadId == upgradeLockOwnerId)

{
throw new LockRecursionException(
GetStringFromResource("LockRecursionException_RecursiveUpgradeNotAllowed"));
}
if (managedThreadId == writeLockOwnerId)

{
throw new LockRecursionException(
GetStringFromResource("LockRecursionException_UpgradeAfterWriteNotAllowed"));
}
EnterMyLock();
threadRWCount = GetThreadRWCount(managedThreadId, true);
if ((threadRWCount != null) && (threadRWCount.readercount > 0))

{
ExitMyLock();
throw new LockRecursionException(
GetStringFromResource("LockRecursionException_UpgradeAfterReadNotAllowed"));
}
}
else

{
EnterMyLock();
threadRWCount = GetThreadRWCount(managedThreadId, false);
if (managedThreadId == upgradeLockOwnerId)

{
threadRWCount.rc.upgradecount++;
ExitMyLock();
return true;
}
if (managedThreadId == writeLockOwnerId)

{
owners++;
upgradeLockOwnerId = managedThreadId;
threadRWCount.rc.upgradecount++;
if (threadRWCount.readercount > 0)

{
fUpgradeThreadHoldingRead = true;
}
ExitMyLock();
return true;
}
if (threadRWCount.readercount > 0)

{
ExitMyLock();
throw new LockRecursionException(
GetStringFromResource("LockRecursionException_UpgradeAfterReadNotAllowed"));
}
}
int spinCount = 0;
Label_0139:
if ((upgradeLockOwnerId == -1) && (owners < 0xffffffe))

{
owners++;
upgradeLockOwnerId = managedThreadId;
}
else

{
if (spinCount < 20)

{
ExitMyLock();
if (millisecondsTimeout == 0)

{
return false;
}
spinCount++;
SpinWait(spinCount);
EnterMyLock();
goto Label_0139;
}
if (upgradeEvent == null)

{
LazyCreateEvent(ref upgradeEvent, true);
goto Label_0139;
}
if (WaitOnEvent(upgradeEvent, ref numUpgradeWaiters, millisecondsTimeout))

{
goto Label_0139;
}
return false;
}
if (fIsReentrant)

{
if (IsRwHashEntryChanged(threadRWCount, managedThreadId))

{
threadRWCount = GetThreadRWCount(managedThreadId, false);
}
threadRWCount.rc.upgradecount++;
}
ExitMyLock();
return true;
}
public bool TryEnterUpgradeableReadLock(TimeSpan timeout)

{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))

{
throw new ArgumentOutOfRangeException("timeout");
}
int millisecondsTimeout = (int)timeout.TotalMilliseconds;
return TryEnterUpgradeableReadLock(millisecondsTimeout);
}
#endregion

#endregion
}
#endregion
}
测试项目见后面下载地址:ReaderWriterLockSlim.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构