Consider this code (from 'C++ concurrency in action' [Second edition]: page 212):
void LockFreeStack::pop (stack_data& result)
{
Node* old_head = head.load();
while(!head.compare_exchange_weak(old_head, old_head->next))
;
result = old_head->data;
}
I think it's possible to thread-one execute pop()
and after executing first line (loading head
) time slicing happened to thread-two, which is executing push(T&)
. So now value of head
atomic variable is not equal to old_head
and while
-loop won't break.
It's right ?
assuming head
is a std::atomic<Node*>
then the code is correct as when compare_exchange_weak
fails it loads the current value of the variable into its first parameter, after the compare_exchange_weak
call old_head
will always contain the current value of head
.
The code is roughly equivalent to doing the following without atomics:
Node* old_head = head;
while (true)
{
std::unique_lock lock(mutex);
if (old_head == head)
{
head = old_head->next;
break;
}
else
{
old_head = head;
}
}
Concurrent calls to pop
are therefore safe and shouldn't block forever (other than due to other threads constantly calling pop and somehow always setting the value before the current thread gets a chance).