Luke Vo
Luke Vo

Reputation: 20668

Is .NET 6 PriorityQueue thread-safe?

.NET 6 now has PriorityQueue<TElement,TPriority> which is very useful. The document is not very clear yet (granted at the time of the question the documentation is still for RC1) if it is thread-safe or not. Two things:

Can I use it for multithreaded environment without wrapping/locking (for example in an ASP.NET Core website)? Any concurrent equivalent that I am not aware of (I try not to use 3rd-party package if possible)?

Upvotes: 5

Views: 3110

Answers (3)

Bluesillybeard2
Bluesillybeard2

Reputation: 51

It is not thread safe. Here is a very simple test:

PriorityQueue<int, int> queue = new PriorityQueue<int, int>();
Parallel.For(0, 10000, (id) => {
    queue.Enqueue(id, 0);
    queue.Dequeue();
});

The test crashes with an exception. It can be easily fixed using lock statements:

PriorityQueue<int, int> queue = new PriorityQueue<int, int>();
Parallel.For(0, 10000, (id) => {
    lock(queue)
    {
        queue.Enqueue(id, 0);
    }
    lock(queue)
    {
        queue.Dequeue();
    }
});

That might cause issues if the queue is being shared, but that can be fixed by using a wrapper class that extends PriorityQueue, overriding every method to include a lock.

Upvotes: 2

TomTom
TomTom

Reputation: 62101

The document is not very clear yet

It actually is. Anything in .NET is NOT thread safe unless it is EXPLICITLY mentioned in the documentation. Period.

Thread safety comes with a (significant) performance overhead, particularly when done generically (i.e. not assuming specific uses). As such, it would be extremely stupid to make everything thread safe "just in case". Hence the general concept in .NET (since back in 1.0) that NOTHING is thread safe unless it is explicitly mentioned in the documentation.

As you say, the documentation has no mention of thread safety. As such, it is extremely clear on NOT being thread safe.

Upvotes: 2

spender
spender

Reputation: 120480

With a look at the source code for PriorityQueue.Enqueue, for instance, it is immediately apparent that the code is not thread-safe:

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

Upvotes: 13

Related Questions