在许多属性中使用ReaderWriterLockSlim的更简洁方法

时间:2012-06-29 17:04:02

标签: c# thread-safety dry readwritelock

我正在尝试实现许多利用ReaderWriterLockSlim来保证线程安全的属性。 所以像大多数人一样,我在所有属性中都得到类似的东西:

public string Name
{
    get
    {
        rwLock.EnterReadLock();
        try {
            return name;
        }
        finally {
            rwLock.ExitReadLock();
        }
    }
    set
    {
        rwLock.EnterWriteLock();
        try {
            name = value;                    
        }
        finally {
            rwLock.ExitWriteLock();
        }
    }
}

这在10个属性中感觉非常冗长和重复,所以我正在寻找更干的实现。

显而易见的解决方案是将它包装到一个释放了dispose锁的类中,并允许我将我的线程安全操作放在using语句中。显然,根据this和其他一些消息来源,这不是很安全。

所以我试图用lambda表达式和匿名方法提出一个漂亮的解决方案:

private TResult ThreadSafeRead<TResult>(Func<TResult> value)
{
    rwLock.EnterReadLock();
    try {
        return value();
    }
    finally {
        rwLock.ExitReadLock();
    }            
}

private void ThreadSafeWrite(Action value)
{
    rwLock.EnterWriteLock();
    try {
        value();
    }
    finally {
        rwLock.ExitWriteLock();
    }
}

public string Name
{
    get { return ThreadSafeRead(() => name); }
    set { ThreadSafeWrite(() => { name = value; }); }
}       

虽然这消除了令我烦恼的重复代码,但我不知道它是否像我原来的详细实现那样是线程安全的。

是否有人对MSIL有了更深入的了解,这将产生多线程 理论能够告诉我我的实施是否安全吗?

2 个答案:

答案 0 :(得分:1)

我见过人们常见的做法是将锁包裹在一个物体中并按照以下方式做一些事情:

using (var obj = new ReadOnlyLock(this.rwLock))
{
    this.name = value;
}

我会承认我不这样做(为什么要创建另一个对象只是为了锁定?)但它确实达到了一些人认为最重要的风格目标......

答案 1 :(得分:0)

您的博客文章中提到的问题确实存在,是的。有关此主题的更全面的处理,请参阅Joe Duffy's post

您的代码是否会受到异步异常的影响?它们很可能只在ASP.NET下运行时发生,当前请求因超时而中止。当然,你不应该出于各种原因自行中止一个帖子。

我认为你不应该真正关心这个问题。