2012-06-29 27 views
1

我正在尝试实现许多使用ReaderWriterLockSlim进行线程安全的属性。 所以最喜欢我结束了我的所有属性是这样的:在很多属性中使用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有更深入的理解,这将会产生多线程 理论能够告诉我我的实现是否安全?

+1

这与线程安全无关。问题来自你的线程调用Thread.Abort。 – usr

回答

1

的常用方法我见过的人去了解,这是通过在物体包裹锁和做线沿线的东西:

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

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

+0

正如我所提到的,封装使用语句是显而易见的解决方案,但我发现许多消息来源都解释说它不是线程安全的。见[这里](http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=21)。 – KrisG

+0

对不起,我不是故意暗示它是完美的。我不使用它。相反,我只是说这是用于解决您的问题的一种常见*模式。 我会承认,我不认为这是一个真正值得解决的问题... –

+1

@KrisG:废话,为什么不是线程安全的? (您链接的文章描述了try-finally的一般问题...) – Cameron

0

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

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

我不认为你应该切实关心这个问题。

相关问题