Search code examples
c#multithreadingqueuethread-safetyconcurrent-queue

Difference between Queue's and Concurrent Queue's TryDequeue method


Both collections, Queue and ConcurrentQueue have a method TryDequeue. What is the difference between using TryDequeue with Queue and ConcurrentQueue respectively? Is Queue's TryDequeue method thread-safe in multi-threading environment?


Solution

  • Queue.TryDequeue() is not threadsafe.

    We can look at its implementation for proof:

    public bool TryDequeue([MaybeNullWhen(false)] out T result)
    {
        int head = _head;
        T[] array = _array;
    
        if (_size == 0)
        {
            result = default;
            return false;
        }
    
        result = array[head];
        if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
        {
            array[head] = default!;
        }
        MoveNext(ref _head);
        _size--;
        _version++;
        return true;
    }
    

    It's easy to see that isn't threadsafe. Just the _size-- alone is not threadsafe.

    But even without the source code, the documentation for Queue<T> explicitly states:

    Any instance members are not guaranteed to be threadsafe.

    Of course, the methods of ConcurrentQueue are threadsafe, and by definition ImmutableQueue is also threadsafe.

    (The Try in the name of TryDequeue() is referring to the fact that it handles an empty queue rather than anything to do with thread safety.)