2

我正在尝试实现许多利用 ReaderWriterLockSlim 实现线程安全的属性。所以像大多数人一样,我最终在我的所有属性中都得到了这样的结果:

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

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

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

所以我尝试使用 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 这将产生和多线程理论有更深入的了解,能够告诉我我的实现是否安全?

4

2 回答 2

1

我见过人们解决这个问题的常用方法是将锁包裹在一个对象中并按照以下方式做一些事情:

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

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

于 2012-06-29T17:08:05.227 回答
-1

您的博文中提到的问题确实存在,是的。有关此主题的更彻底处理,请参阅Joe Duffy 的帖子

您的代码是否甚至遭受异步异常?它们很可能只在 ASP.NET 下运行并且当前请求由于超时而中止时发生。当然,您永远不应该出于各种原因自己中止线程。

我认为您实际上不应该关心这个问题。

于 2012-06-29T17:19:31.167 回答