Thread Safety in .NET TPL Data Stream Source

I was looking for an implementation for some parts of the .NET TPL "Dataflow" library out of curiosity, and I came across the following snippet:

    private void GetHeadTailPositions(out Segment head, out Segment tail,
        out int headLow, out int tailHigh)
    {
        head = _head;
        tail = _tail;
        headLow = head.Low;
        tailHigh = tail.High;
        SpinWait spin = new SpinWait();

        //we loop until the observed values are stable and sensible.  
        //This ensures that any update order by other methods can be tolerated.
        while (
            //if head and tail changed, retry
            head != _head || tail != _tail
            //if low and high pointers, retry
            || headLow != head.Low || tailHigh != tail.High
            //if head jumps ahead of tail because of concurrent grow and dequeue, retry
            || head._index > tail._index)
        {
            spin.SpinOnce();
            head = _head;
            tail = _tail;
            headLow = head.Low;
            tailHigh = tail.High;
        }
    }

(can be viewed here: https://github.com/dotnet/corefx/blob/master/src/System.Threading.Tasks.Dataflow/src/Internal/ConcurrentQueue.cs#L345 )

From what I understand regarding thread safety, this operation is subject to data race. I am going to explain my understanding, and then what I perceive as a β€œmistake”. Of course, I expect that this is more of a mistake in my mental model than in the library, and I hope that someone here can indicate where I am making a mistake.

...

(head, tail, head.Low tail.High) . :

  • , ,
  • - , CLR/JIT ""

, , :

  • ConcurrentQueue ( head, tail, head.Low tail.High).
  • .
  • , 2
  • , ""

, , , "" : . , (, head, tail).

, - head tail , / , CAS/spin.

, , . "" , , ? ""? : , , -, , , ?

+4
1

, , out GetHeadTailPositions ToList, Count GetEnumerator.

, . ConcurrentQueue<T>._numSnapshotTakers , .

ConcurrentQueue <T> , , :

, .NET 4 " ". . ConcurrentQueue <T> " " , , , , ConcurrentQueue <T> , , , , . , , .

.NET 4.5 , , . , , , , , .NET 4. , ConcurrentQueue <T> , dequeues , dequeued. dequeue - (.. GetEnumerator ), ; .NET 4, , .

, ( GetEnumerator<T>, GetEnumerator), ToList ( ToArray, ToList) TryPeek , . , TryDequeue ( ConcurrentQueue<T>.Segment.TryRemove) TryPeek , .

+2

Source: https://habr.com/ru/post/1666279/


All Articles