摘要:做线程同步的时候一般都用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
{