c#中的队列同步和操作
本文关键字:操作 同步 队列 | 更新日期: 2023-09-27 18:02:50
如果队列已同步:
var _item = Queue.Synchronized(new Queue());
我可以在不使用锁语句的情况下调用Enqueue和Dequeue方法吗?
我当前的代码是:
lock (_item.SyncRoot)
{
_item.Enqueue(obj);
}
我可以线程安全地使用:
_item.Enqueue(obj);
var item = _item.Dequeue();
调用Enqueue
和Dequeue
是线程安全的。
但是,您的示例代码不是:
在调用Enqueue
和调用Dequeue
之间可能存在线程切换。这意味着,item
可能是obj
的另一个实例,或者对Dequeue
的调用会抛出异常,因为它现在是空的。
lock(_item.SyncRoot)
{
_item.Enqueue(obj);
var item = _item.Dequeue);
}
现在可以保证item
在任何情况下都等于obj
这几乎就是SynchronizedQueue
所做的,但有一个问题…通常你需要在一个原子单元中检查.Count
和 .Dequeue()
-而不是检查.Count
(一个单元)然后.Dequeue()
(另一个单元)-一旦锁被放弃,你就不能信任.Count
,如果另一个线程窃取了工作,.Dequeue()
会抛出。
也许尝试ConcurrentQueue<T>
在4.0(与.TryDequeue()
),或使用Queue<T>
和lock
。
From MSDN
的线程安全队列中,所有的操作都必须完成枚举一个集合是本质上不是线程安全的过程。即使一个集合是同步后,其他线程仍然可以修改集合,会导致抛出异常的枚举数。期间的线程安全枚举,则可以锁定整个期间的收集枚举或捕获异常由于他人的改变而产生的线程。
正如John Skeet的回答所建议的那样,由于枚举可能会导致异常,因此使用锁可能会更好。
Gregs的回答还谈到了Marc提到的Count
不是线程安全的。