編輯:正如它被注意到,我寫了功能與完全相反的語義 - 只入隊到一個空隊列。我固定了這個名字以反映這一點,並決定放棄它,以防萬一有人感興趣。所以,這是不正確的答案的問題,但不downvote請,除非你找到另一個原因:)
下面是一個企圖在引用的文件添加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;
}
此代碼有一個微妙的錯誤。正如文檔所述(http://www.boyet.com/articles/ABAProblem.html),它在C#中工作,因爲垃圾收集。它將**不工作**在C中。 – 2011-05-03 03:13:39
我正在使用引用計數系統來解決隊列中節點上的ABA問題。所以保證節點不會早早釋放。 – luke 2011-05-03 03:34:38
我從來沒有遇到任何基於ref count的解決方案,它允許免費()的隊列元素。我可以想象一個基於ref count的解決方案,它允許元素返回freelist,但就是這樣。你是否說過你已經設計了基於ref count的安全內存回收算法? – 2011-05-04 11:01:35