- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在使用这段代码在 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 倍,性能仍然(几乎)相同。
我是不是做错了什么?
亲切的问候。
最佳答案
在您的示例中, sleep 意味着通常没有争用。无竞争锁非常快。为此,您需要一个竞争锁;如果在该争用中有写入,它们应该大致相同(lock
甚至可能更快) - 但如果它是大部分读取(很少有写入争用),我希望 ReaderWriterLockSlim
锁的性能优于 lock
。
就个人而言,我更喜欢这里的另一种策略,使用引用交换 - 因此读取始终可以读取而无需检查/锁定等。写入将它们更改为克隆副本,然后使用 Interlocked.CompareExchange
以交换引用(如果另一个线程在此期间更改了引用,则重新应用它们的更改)。
关于c# - ReaderWriterLockSlim 什么时候比简单的锁更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217398/
有很多关于 ReaderWriterLockSlim 类的文章,它允许多次读取和一次写入。所有这些(至少我发现的)都告诉了如何使用它,而没有太多解释它为什么以及如何工作。标准代码示例是: lock.E
我对 ReaderWriterLockSlim 和延迟 ExitWriteLock 感到沮丧。为什么定时器回调中会释放WriteLock? var _lock = new ReaderWriterLo
我围绕 ReaderWriterLockSlim 编写了一个相当简单的包装器: class SimpleReaderWriterLock { private class Guard : IDi
编辑: 从我已经得到的答案来看,我了解到我提出的第一个解决方案并不是真正的“不阻塞读取”,因为只有一个线程可以进入可升级锁而写锁不能在阅读发布之前采取... 所以我的问题是,如果不存在,如何以正确的方
我正在为在 Windows Azure 中运行的应用程序编写全局错误处理程序/记录器。当应用程序中发生错误时,会执行许多需要自动发生的操作。我需要防止在前一个错误完成之前记录错误。同时,我希望根据需要
我正在编写一个广泛使用多线程的应用程序。一些线程使用 ReaderWriterLockSlim 共享一个 observablecollection。 我有时会遇到死锁,我需要知道在死锁发生时哪个线程持
我有一节课使用 ReaderWriterLockSlim具有一个读取方法和一个写入方法,该方法使用读取方法检索要修改的元素。一个简单的例子是: class FooLocker { Reader
我遇到了这个异常 正在释放读锁而不被持有。 在 System.Threading.ReaderWriterLockSlim.ExitReadLock() 在 .. GetBreed(字符串) 下面是代
我一直在研究集合和线程,并发现了人们创建的漂亮的扩展方法,它们通过允许 IDisposable 模式来简化 ReaderWriterLockSlim 的使用。 但是,我相信我已经意识到实现中的某些东西
我正在使用这段代码在 ReaderWriterLock 上做一个非常愚蠢的基准测试,其中读取的频率是写入的 4 倍: class Program { static void Main()
目前我正在使用 WinDbg 分析转储。 我运行了以下命令(遵循 Tess' incredible walkthrough ): ~* e !clrstack 其中列出了所有线程的所有堆栈。有 300
我正在使用 ReaderWriterLockSlim保护一些操作。我想偏爱读者而不是作者,这样当读者长时间持有锁并且作者试图获取写锁时,进一步的读者不会被作者的尝试阻塞(如果作者在 lock.Ente
Based on Microsoft documentation EnterReadLock 用于在读取模式下锁定。它还表示多个线程可以读取,但一次只能有一个线程写入。 为什么我们应该使用 Enter
我想检查以下代码是否可以抵抗 ThreadAbortException 并且不会导致孤儿锁。如果不是,避免孤儿锁的最佳模式是什么? ReaderWriterLockSlim _lock = new R
我正在使用 ConcurrentBag 在运行时存储对象。在某些时候,我需要清空包并将包中的内容存储到列表中。这就是我所做的: IList list = new List();
我正在调试针对 .NET 3.5 的托管应用程序中的挂起。其中一个线程永远等待方法 System.Threading.ReaderWriterLockSlim.EnterWriteLock。为了找出哪
是否有等效的 Monitor.Pulse 和 Monitor.Wait 可以与 ReaderWriterLockSlim 结合使用? 我有一个类,其中封装了对底层队列的多线程访问。为了对某些东西进行排
我正在尝试实现许多利用 ReaderWriterLockSlim 实现线程安全的属性。所以像大多数人一样,我最终在我的所有属性中都有这样的东西: public string Name { ge
我有一个类 MyClass。此类有一个字段:public ReaderWriterLockSlim rw;(public 用于更简单的示例代码)。许多线程可以使用 rw.EnterReadLock 等
我一直在使用 ReaderWriterLockSlim一段时间以来,它已经满足了我的需求。当我继续微调我的应用程序时,我发现 ReaderWriterLockSlim 对于我的用例来说略显次优。 根据
我是一名优秀的程序员,十分优秀!