C# 中的队列同步和操作

发布于 2024-11-24 20:53:49 字数 322 浏览 0 评论 0原文

如果队列是同步的:

var _item = Queue.Synchronized(new Queue());

我可以在不使用lock语句的情况下调用Enqueue和Dequeue等方法吗?

我当前的代码是:

lock (_item.SyncRoot)
{
    _item.Enqueue(obj);
}

我可以线程安全地使用:

_item.Enqueue(obj);
var item = _item.Dequeue();

If a Queue is syncronized:

var _item = Queue.Synchronized(new Queue());

can I call methods like Enqueue and Dequeue on it without using lock statements?

My current code is:

lock (_item.SyncRoot)
{
    _item.Enqueue(obj);
}

Can I thread-safely use:

_item.Enqueue(obj);
var item = _item.Dequeue();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紧拥背影 2024-12-01 20:53:49

Enqueue 的调用和对 Dequeue 的调用是线程安全的。
但是,您的示例代码不是:
在对 Enqueue 的调用和对 Dequeue 的调用之间可能存在线程切换。这意味着,item 可能是 obj 之外的另一个实例,或者调用 Dequeue 会引发异常,因为它现在是空的。

为了使示例代码线程安全,您仍然需要显式锁定:

lock(_item.SyncRoot)
{
    _item.Enqueue(obj);
    var item = _item.Dequeue);
}

只有现在才能保证 item 引用在所有情况下都等于 obj

The call to Enqueue and the call to Dequeue are thread safe.
However, your sample code is not:
Between the call to Enqueue and the call to Dequeue there could have been a thread switch. This means, that item might be another instance than obj or the call to Dequeue throws an exception, because it now is empty.

To make your sample code thread safe, you still need to lock explicitly:

lock(_item.SyncRoot)
{
    _item.Enqueue(obj);
    var item = _item.Dequeue);
}

Only now it is guaranteed, that item reference-equals obj in all circumstances.

月隐月明月朦胧 2024-12-01 20:53:49

这几乎就是 SynchronizedQueue 所做的,但是有一个问题......通常您需要检查 .Count < /strong> .Dequeue() 在一个原子单元中 - 不检查 .Count (一个单元)然后 .Dequeue() (另一个单元) ) - 你不能相信 .Count一旦锁被交出,完全,如果另一个线程窃取了工作,.Dequeue()将抛出异常。

也许在 4.0 中尝试 ConcurrentQueue(使用 .TryDequeue()),或使用 Queuelock

That is pretty much what SynchronizedQueue does, but there is a problem... typically you need to check the .Count and .Dequeue() in one atomic unit - not check the .Count (one unit) then .Dequeue() (another unit) - you can't trust .Count at all once the lock is surrendered, and .Dequeue() will throw if another thread has stolen the work.

Maybe try ConcurrentQueue<T> in 4.0 (with .TryDequeue()), or use Queue<T> and lock.

小清晰的声音 2024-12-01 20:53:49

来自 MSDN

保证线程安全
队列,所有操作都必须完成
仅通过此包装器。

通过集合进行枚举是
本质上不是线程安全的
程序。即使是一个集合
同步后,其他线程仍然可以
修改集合,这会导致
枚举器抛出异常。
保证期间的线程安全
枚举,您可以锁定
整个过程中采集
枚举或捕获异常
由其他人所做的更改引起的
线程。

正如约翰·斯基特的回答所暗示的在这里,您可能更好或使用锁定,因为枚举可能会导致异常。

格雷格斯answer 还讨论了 Marc 提到的 Count 不是线程安全的问题。

From MSDN

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.

Just as John Skeet's answer suggests here, you might be better or using locking since enumerating might cause an exception.

Gregs answer also talks about what Marc mentions with the Count not being thread safe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文