I was reading the source code of ConcurrentQueue, here are some code:
/// <summary>
/// Store the position of the current head and tail positions.
/// </summary>
/// <param name="head">return the head segment</param>
/// <param name="tail">return the tail segment</param>
/// <param name="headLow">return the head offset, value range [0, SEGMENT_SIZE]</param>
/// <param name="tailHigh">return the tail offset, value range [-1, SEGMENT_SIZE-1]</param>
private void GetHeadTailPositions(out Segment head, out Segment tail,
    out int headLow, out int tailHigh)
{
    head = m_head;
    tail = m_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 != m_head || tail != m_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.m_index > tail.m_index)
    {
        spin.SpinOnce();
        head = m_head;
        tail = m_tail;
        headLow = head.Low;
        tailHigh = tail.High;
    }
}
GetHeadTailPositions() may want to get 4 variables at a particular time, however, there are 4 compare in the 'where' loop, think about the below sequence:
while (
    // 1. head equals m_head
    head != m_head 
    // 2. m_head was changed while other variables were unchanged
    || tail != m_tail || headLow != head.Low || tailHigh != tail.High || head.m_index > tail.m_index)
{
    // ...
}
then we get a unstable version of these variables. Is this method stable? How to get a stable version of mutiple values at a particular time without lock?
 
    