【发布时间】:2010-12-26 09:26:26
【问题描述】:
在编写一些线程代码时,我一直在使用ReaderWriterLockSlim 类来处理对变量的同步访问。这样做时,我注意到我一直在编写 try-finally 块,每个方法和属性都一样。
看到有机会避免重复自己并封装这种行为,我构建了一个类ReaderWriterLockSection,旨在用作锁的瘦包装器,可与 C# using 块语法一起使用。
类大多如下:
public enum ReaderWriterLockType
{
Read,
UpgradeableRead,
Write
}
public class ReaderWriterLockSection : IDisposeable
{
public ReaderWriterLockSection(
ReaderWriterLockSlim lock,
ReaderWriterLockType lockType)
{
// Enter lock.
}
public void UpgradeToWriteLock()
{
// Check lock can be upgraded.
// Enter write lock.
}
public void Dispose()
{
// Exit lock.
}
}
我使用的部分如下:
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void Foo()
{
using(new ReaderWriterLockSection(_lock, ReaderWriterLockType.Read)
{
// Do some reads.
}
}
对我来说,这似乎是一个好主意,它使我的代码更易于阅读并且看起来更健壮,因为我永远不会忘记释放锁。
任何人都可以看到这种方法的问题吗?有什么理由这是一个坏主意吗?
【问题讨论】:
-
我建议你改用结构体,以避免 GC 开销。
-
使用结构体会导致装箱,因为结构体将实现 IDisposable,这意味着对构造函数和 Dispose 方法的所有调用都会对结构体进行装箱/拆箱,这会减慢主线程的速度,还会导致一些箱体停留在 GC 堆上,从而否定结构的使用。
-
具有实现 IDisposable 的结构/值类型的 using 子句不会将值装箱,而是直接在结构上调用 Dispose,这将按预期工作。如果他可能会传递节值的可能性很小,那么结构是不可用的,但如果唯一的用途是用于这样的 using 块,那么结构将避免 GC 开销并按建议工作。
-
当然,如果您明确地将其强制转换为 IDisposable,或者将其从 SectionFactory-type-method 作为 IDisposable 返回,那么它将被装箱。我建议您直接返回和/或将其声明为值类型,这将避免装箱和别名。换句话说,如果 ReaderWriterLockSection 是一个结构,那么问题底部的代码就可以工作。
-
详情请见billrob.com/archive/2006/05/12/530.aspx(Eric Lippert 的评论)
标签: c# .net multithreading readerwriterlockslim