问题描述
我在做一件很无聊的基准与此code,其中的阅读发生的4倍以上往往比书面方式在ReaderWriterLock:
I'm doing a very silly benchmark on the ReaderWriterLock with this code, where reading happens 4x more often than writting:
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";
}
}
不过,我得到了两个或多或少以同样的方式进行:
But I get that both perform in more or less the same way:
Locked: 25003ms.
RW Locked: 25002ms.
End
甚至使阅读20次更多的时候写入,性能仍然是(几乎)相同。
Even making the read 20 times more often that writes, the performance is still (almost) the same.
难道我做错了吗?
亲切的问候。
推荐答案
在你的榜样,在睡觉意味着的一般的没有争。一个无竞争锁是非常快的。对于这事,你需要一个的争辩的锁;如果有写的在这争,他们应该是差不多的(锁定
甚至更快) - 但如果它的大多的读取(与写入争很少),我预计 ReaderWriterLockSlim
锁外执行锁定
。
In your example, the sleeps mean that generally there is no contention. An uncontended lock is very fast. For this to matter, you would need a contended lock; if there are writes in that contention, they should be about the same (lock
may even be quicker) - but if it is mostly reads (with a write contention rarely), I would expect the ReaderWriterLockSlim
lock to out-perform the lock
.
就个人而言,我在这里preFER另一种策略,使用引用交换 - 这样可以读取,读而没有检查/锁定/等写入使他们改变到的克隆的副本,然后使用 Interlocked.CompareExchange
来交换引用(再运用自己的改变,如果另一个线程突变在此期间参考)。
Personally, I prefer another strategy here, using reference-swapping - so reads can always read without ever checking / locking / etc. Writes make their change to a cloned copy, then use Interlocked.CompareExchange
to swap the reference (re-applying their change if another thread mutated the reference in the interim).
这篇关于如果是ReaderWriterLockSlim不是一个简单的锁比较好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!