这是一个危险的锁定模式吗?
我有一个用 C# 编写的枚举器,看起来像这样:
try
{
ReadWriteLock.EnterReadLock();
yield return foo;
yield return bar;
yield return bash;
}
finally
{
if (ReadWriteLock.IsReadLockHeld)
ReadWriteLock.ExitReadLock();
}
我相信这可能是一种危险的锁定模式,因为只有在枚举完成时 ReadWriteLock 才会被释放,否则锁会挂起并且永远不会被释放,是吗?正确的?如果是这样,解决这个问题的最佳方法是什么?
I have an enumerator written in C#, which looks something like this:
try
{
ReadWriteLock.EnterReadLock();
yield return foo;
yield return bar;
yield return bash;
}
finally
{
if (ReadWriteLock.IsReadLockHeld)
ReadWriteLock.ExitReadLock();
}
I believe this may be a dangerous locking pattern, as the ReadWriteLock will only be released if the enumeration is complete, otherwise the lock is left hanging and is never released, am I correct? If so, what's the best way to combat this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,
finally
块将始终被执行,除非有人从计算机上拔掉插头(好吧,还有一些其他例外)。...
上面的输出将是
请注意,在 C# 中,您编写的是
yield return
,而不仅仅是yield
。但我想这只是一个错字。No, the
finally
block will always be executed, pretty much unless somebody pulls the plug from the computer (well and a few other exceptions)....
The output of the above will be
Note that in C# you write
yield return
, not justyield
. But I guess that was just a typo.我认为大卫回答了你想问的问题(关于枚举方面),但还有两点需要考虑:
在#1 中,您将不恰当地调用
ReadWriteLock.ExitReadLock
。在 #2 中,您可以隐藏已引发的现有异常(因为finally
子句发生是因为主线处理到达try
块的末尾或 因为抛出了异常;在后一种情况下,您可能不想掩盖异常)。也许在这种特定情况下,这两件事都不太可能发生,但您询问了模式,并且作为一种模式,它存在这些问题。I think David's answered the question you intended to ask (about the enumeration aspect), but two additional points to consider:
ReadWriteLock.EnterReadLock
threw an exception?ReadWriteLock.ExitReadLock
threw an exception?In #1, you'll call
ReadWriteLock.ExitReadLock
inappropriately. In #2, you may hide an existing exception that's been thrown (sincefinally
clauses happen either because the mainline processing reached the end of thetry
block or because an exception was thrown; in the latter case, you probably don't want to obscure the exception). Perhaps both of those things are unlikely in this specific case, but you asked about the pattern, and as a pattern it has those issues.无论如何,finally都会被执行,但是对于锁定来说可能并不安全。比较以下方法:
输出为:
如果您的处理需要很多时间(每次迭代),那么先填充集合,然后处理,而不是yield 更合理。
Finally will be executed in any way, but for locking in may not be safe. Compare following methods:
Output is:
If your processing takes much time (per iteration) it is more reasonable to fill collection first, then process, but not yield.