【问题标题】:Is .NET 6 PriorityQueue thread-safe?.NET 6 PriorityQueue 线程安全吗?
【发布时间】:2021-12-27 09:40:21
【问题描述】:

.NET 6 现在有PriorityQueue<TElement,TPriority>,这非常有用。该文档还不是很清楚(在提出问题时授予该文档仍然适用于 RC1)它是否是线程安全的。两件事:

  • 它位于System.Collections.Generic 中,而System.Collections.Concurrent 中似乎没有等价物。

  • 它确实有名为TryDequeueTryPeek 的方法。当然,它们可能只是在队列为空时不会抛出异常的方法,但它确实给人一种并发集合的印象。

我可以将它用于多线程环境而不进行包装/锁定(例如在 ASP.NET Core 网站中)吗?任何我不知道的并发等效项(如果可能,我尽量不使用 3rd-party 包)?

【问题讨论】:

  • 这有点遗漏——通常 MSDN 文档擅长说明一个类型是否是线程安全的。然而,看看the source,很明显它不是线程安全的。您将需要使用自己的锁定。
  • 在我看来,最简单的规则是,如果类型没有明确声明它是线程安全的(或者有暗示它的名称),你应该假设它不是.
  • 这不仅是您的规则 - 它是编写 .NET 的一般方式。线程安全是一项罕见的功能,需要付出一定的代价。除非明确提及,否则默认情况下某些东西不是线程安全的。因此,文档非常清楚这不是线程安全的。
  • 没有。着眼于大局,PriorityQueue 的重点是迭代。您按优先顺序取回元素。迭代永远不是线程安全的。安全集合类通过让枚举器复制集合来伪造它,这只会使其在逻辑上安全。但是很昂贵,并且不会阻止不再出现在集合中的元素出现。只有使用 lock 的客户端代码才能使其真正安全,小心锁定迭代器循环的痛苦。

标签: c# .net multithreading priority-queue .net-6.0


【解决方案1】:

例如,查看PriorityQueue.Enqueuesource code,很明显代码不是线程安全的:

public void Enqueue(TElement element, TPriority priority)
{
    // Virtually add the node at the end of the underlying array.
    // Note that the node being enqueued does not need to be physically placed
    // there at this point, as such an assignment would be redundant.

    int currentSize = _size++; // <-- BOOM

【讨论】:

    【解决方案2】:

    文档还不是很清楚

    确实如此。 .NET 中的任何内容都不是线程安全的,除非文档中明确提及。期间。

    线程安全伴随着(显着的)性能开销,尤其是在一般情况下(即不假设特定用途)。因此,让所有线程安全“以防万一”将是非常愚蠢的。因此,.NET 中的一般概念(从 1.0 开始)认为没有什么是线程安全的,除非在文档中明确提及。

    正如你所说,文档没有提到线程安全。因此,非常清楚不是线程安全的。

    【讨论】:

    • 如果这通过遗漏非常清楚,那么所有具有“线程安全”部分的类型都说“这不是线程安全的”,例如非优先Queue&lt;T&gt; class?由于 MSDN 文档中的总体约定是有一个“线程安全”部分,无论该类型是否是线程安全的,因此缺少任何此类部分更多地表明该类型不是线程安全的......
    • 这需要对 .NET 文档有广泛的了解,即不是很明显。
    猜你喜欢
    • 2013-06-10
    • 2010-09-28
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多