问题描述
我有一个 Queue 对象,我需要确保它是线程安全的.使用这样的锁对象会更好:
I have a Queue object that I need to ensure is thread-safe. Would it be better to use a lock object like this:
lock(myLockObject)
{
//do stuff with the queue
}
还是建议这样使用Queue.Synchronized:
Or is it recommended to use Queue.Synchronized like this:
Queue.Synchronized(myQueue).whatever_i_want_to_do();
通过阅读 MSDN 文档,它说我应该使用 Queue.Synchronized 使其成为线程安全的,但随后它给出了一个使用锁定对象的示例.来自 MSDN 文章:
From reading the MSDN docs it says I should use Queue.Synchronized to make it thread-safe, but then it gives an example using a lock object. From the MSDN article:
为了保证线程的安全队列,所有操作都必须完成仅通过此包装器.
To guarantee the thread safety of the Queue, all operations must be done through this wrapper only.
通过集合枚举是本质上不是线程安全的程序.即使是一个集合同步,其他线程仍然可以修改集合,这会导致枚举器抛出异常.为了保证线程安全枚举,您可以锁定在整个收集枚举或捕获异常由其他人所做的更改导致线程.
Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads can still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or catch the exceptions resulting from changes made by other threads.
如果调用 Synchronized() 不能确保线程安全,那有什么意义呢?我在这里遗漏了什么吗?
If calling Synchronized() doesn't ensure thread-safety what's the point of it? Am I missing something here?
推荐答案
我个人更喜欢加锁.这意味着您可以决定粒度.如果您只依赖 Synchronized 包装器,则每个单独的操作都是同步的,但如果您需要做不止一件事(例如遍历整个集合),则无论如何都需要锁定.为了简单起见,我更喜欢只记住一件事 - 适当地锁定!
Personally I always prefer locking. It means that you get to decide the granularity. If you just rely on the Synchronized wrapper, each individual operation is synchronized but if you ever need to do more than one thing (e.g. iterating over the whole collection) you need to lock anyway. In the interests of simplicity, I prefer to just have one thing to remember - lock appropriately!
如评论中所述,如果您可以使用更高级别的抽象,那就太好了.如果您确实使用锁定,请小心使用它 - 记录您希望在何处锁定的内容,并在尽可能短的时间内获取/释放锁定(更多的是为了正确性而不是性能).避免在持有锁时调用未知代码,避免嵌套锁等.
As noted in comments, if you can use higher level abstractions, that's great. And if you do use locking, be careful with it - document what you expect to be locked where, and acquire/release locks for as short a period as possible (more for correctness than performance). Avoid calling into unknown code while holding a lock, avoid nested locks etc.
在 .NET 4 中,很多支持更高级别的抽象(包括无锁代码).无论哪种方式,我仍然不建议使用同步包装器.
In .NET 4 there's a lot more support for higher-level abstractions (including lock-free code). Either way, I still wouldn't recommend using the synchronized wrappers.
这篇关于在 C# 中使用 Queue.Synchronized 或 lock() 来确保线程安全会更好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!