我知道阻塞队列和无锁队列,这是Scott 等人提供的这些实现的一个很好的例子。,但是有无锁阻塞队列的实现吗?
在无锁阻塞队列中,出队不需要锁定,但如果队列中没有项目,它将阻塞消费者。有没有这种野兽的实现?我更喜欢它们是 C# 实现,但任何实现在技术上都可以工作。
更新:
我想我最终在 D14.1 行出现了竞争条件:
initialize(Q: pointer to queue t)
node = new node() // Allocate a free node
node–>next.ptr = NULL // Make it the only node in the linked list
Q–>Head = Q–>Tail = node // Both Head and Tail point to it
signal = new ManualResetEvent() // create a manual reset event
enqueue(Q: pointer to queue t, value: data type)
E1: node = new node() // Allocate a new node from the free list
E2: node–>value = value // Copy enqueued value into node
E3: node–>next.ptr = NULL // Set next pointer of node to NULL
E4: loop // Keep trying until Enqueue is done
E5: tail = Q–>Tail // Read Tail.ptr and Tail.count together
E6: next = tail.ptr–>next // Read next ptr and count fields together
E7: if tail == Q–>Tail // Are tail and next consistent?
E8: if next.ptr == NULL // Was Tail pointing to the last node?
E9: if CAS(&tail.ptr–>next, next, <node, next.count+1>) // Try to link node at the end of the linked list
E10.1: signal.Set() // Signal to the blocking dequeues
E10.2: break // Enqueue is done. Exit loop
E11: endif
E12: else // Tail was not pointing to the last node
E13: CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) // Try to swing Tail to the next node
E14: endif
E15: endif
E16: endloop
E17: CAS(&Q–>Tail, tail, <node, tail.count+1>) // Enqueue is done. Try to swing Tail to the inserted node
dequeue(Q: pointer to queue t, pvalue: pointer to data type): boolean
D1: loop // Keep trying until Dequeue is done
D2: head = Q–>Head // Read Head
D3: tail = Q–>Tail // Read Tail
D4: next = head–>next // Read Head.ptr–>next
D5: if head == Q–>Head // Are head, tail, and next consistent?
D6: if head.ptr == tail.ptr // Is queue empty or Tail falling behind?
D7: if next.ptr == NULL // Is queue empty?
D8.1: signal.WaitOne() // Block until an enqueue
D8.X: // remove the return --- return FALSE // Queue is empty, couldn’t dequeue
D9: endif
D10: CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) // Tail is falling behind. Try to advance it
D11: else // No need to deal with Tail
// Read value before CAS, otherwise another dequeue might free the next node
D12: *pvalue = next.ptr–>value
D13: if CAS(&Q–>Head, head, <next.ptr, head.count+1>) // Try to swing Head to the next node
D14.1: if(head.ptr == tail.ptr && next.ptr==NULL) // Is queue empty? <--- POSSIBLE RACE CONDITION???
D14.2: signal.Reset()
D14.3: break // Dequeue is done. Exit loop
D15: endif
D16: endif
D17: endif
D18: endloop
D19: free(head.ptr) // It is safe now to free the old dummy node
D20: return TRUE // Queue was not empty, dequeue succeeded