编辑:正如人们注意到的那样,我用完全相反的语义编写了这个函数——只排入一个空队列。我修改了名称以反映这一点,并决定保留它以防万一有人感兴趣。所以,这不是问题的正确答案,但请不要投反对票,除非你找到其他原因:)
EnqueueIfEmpty()
下面是在参考论文中添加到队列实现的尝试。我没有验证它是否有效,甚至可以编译。基本思想是在头部(而不是尾部)之后插入一个新节点,前提是头部的下一个当前为空(这是空队列的必要条件)。我留下了额外的检查头部等于尾部,这可能可以被删除。
public bool EnqueueIfEmpty(T item) {
// Return immediately if the queue is not empty.
// Possibly the first condition is redundant.
if (head!=tail || head.Next!=null)
return false;
SingleLinkNode<T> oldHead = null;
// create and initialize the new node
SingleLinkNode<T> node = new SingleLinkNode<T>();
node.Item = item;
// loop until we have managed to update the tail's Next link
// to point to our new node
bool Succeeded = false;
while (head==tail && !Succeeded) {
// save the current value of the head
oldHead = head;
// providing that the tail still equals to head...
if (tail == oldHead) {
// ...and its Next field is null...
if (oldhead.Next == null) {
// ...try inserting new node right after the head.
// Do not insert at the tail, because that might succeed
// with a non-empty queue as well.
Succeeded = SyncMethods.CAS<SingleLinkNode<T>>(ref head.Next, null, node);
}
// if the head's Next field was non-null, another thread is
// in the middle of enqueuing a new node, so the queue becomes non-empty
else {
return false;
}
}
}
if (Succeeded) {
// try and update the tail field to point to our node; don't
// worry if we can't, another thread will update it for us on
// the next call to Enqueue()
SyncMethods.CAS<SingleLinkNode<T>>(ref tail, oldHead, node);
}
return Succeeded;
}