我正在使用这段代码对 ReaderWriterLock 进行一个非常愚蠢的基准测试,其中读取的频率比写入的频率高 4 倍:
class Program
{
static void Main()
{
ISynchro[] test = { new Locked(), new RWLocked() };
Stopwatch sw = new Stopwatch();
foreach ( var isynchro in test )
{
sw.Reset();
sw.Start();
Thread w1 = new Thread( new ParameterizedThreadStart( WriteThread ) );
w1.Start( isynchro );
Thread w2 = new Thread( new ParameterizedThreadStart( WriteThread ) );
w2.Start( isynchro );
Thread r1 = new Thread( new ParameterizedThreadStart( ReadThread ) );
r1.Start( isynchro );
Thread r2 = new Thread( new ParameterizedThreadStart( ReadThread ) );
r2.Start( isynchro );
w1.Join();
w2.Join();
r1.Join();
r2.Join();
sw.Stop();
Console.WriteLine( isynchro.ToString() + ": " + sw.ElapsedMilliseconds.ToString() + "ms." );
}
Console.WriteLine( "End" );
Console.ReadKey( true );
}
static void ReadThread(Object o)
{
ISynchro synchro = (ISynchro)o;
for ( int i = 0; i < 500; i++ )
{
Int32? value = synchro.Get( i );
Thread.Sleep( 50 );
}
}
static void WriteThread( Object o )
{
ISynchro synchro = (ISynchro)o;
for ( int i = 0; i < 125; i++ )
{
synchro.Add( i );
Thread.Sleep( 200 );
}
}
}
interface ISynchro
{
void Add( Int32 value );
Int32? Get( Int32 index );
}
class Locked:List<Int32>, ISynchro
{
readonly Object locker = new object();
#region ISynchro Members
public new void Add( int value )
{
lock ( locker )
base.Add( value );
}
public int? Get( int index )
{
lock ( locker )
{
if ( this.Count <= index )
return null;
return this[ index ];
}
}
#endregion
public override string ToString()
{
return "Locked";
}
}
class RWLocked : List<Int32>, ISynchro
{
ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
#region ISynchro Members
public new void Add( int value )
{
try
{
locker.EnterWriteLock();
base.Add( value );
}
finally
{
locker.ExitWriteLock();
}
}
public int? Get( int index )
{
try
{
locker.EnterReadLock();
if ( this.Count <= index )
return null;
return this[ index ];
}
finally
{
locker.ExitReadLock();
}
}
#endregion
public override string ToString()
{
return "RW Locked";
}
}
但我知道两者的表现或多或少是相同的:
Locked: 25003ms.
RW Locked: 25002ms.
End
即使读取频率比写入频率高 20 倍,性能仍然(几乎)相同。
我在这里做错了什么吗?
亲切的问候。
在你的例子中,睡眠意味着一般来说没有争议。无竞争锁速度非常快。为此,您需要一个争辩的锁;如果有writes在该争论中,它们应该大致相同(lock
甚至可能更快) - 但如果是的话mostly读取(很少有写入争用),我希望ReaderWriterLockSlim
锁定以超越lock
.
就我个人而言,我更喜欢这里的另一种策略,使用引用交换 - 因此读取始终可以读取而无需检查/锁定/等。写入将其更改为cloned复制,然后使用Interlocked.CompareExchange
交换引用(如果另一个线程在此期间改变了引用,则重新应用它们的更改)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)