Цитируется из C ++ Параллелизм в действии 7.2.5-Применение модели памяти к стеку без блокировки.
Следующий код цитируется в книге. И я знаю, что это нормально, когда есть только одна популярная тема. Но если есть два всплывающих потока, без правила о последовательности выпуска, можно ли безопасно использовать memory_order_acquire
.
Насколько мне известно, мне нужно заменить memory_order_acquire на memory_order_acq_rel
, что приведет к синхронизации между двумя потоками pop. Но в книге сказано, что memory_order_acquire
достаточно.
Неужели мое понимание memory_order_acquire неверно: сбор и выпуск не должны быть сопряжены ?
template<typename T>
class lock_free_stack
{
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
// problem here
while(!head.compare_exchange_strong(old_counter,new_counter
,std::memory_order_acquire,std::memory_order_relaxed));
old_counter.external_count=new_counter.external_count;
}
std::shared_ptr<T> pop()
{
counted_node_ptr old_head=head.load();
for(;;)
{
// call
increase_head_count(old_head);
node* const ptr=old_head.ptr;
if(!ptr)
{
return std::shared_ptr<T>();
}
if(head.compare_exchange_strong(old_head,ptr->next))
{
// todo delete
}
else if(ptr->internal_count.fetch_sub(1)==1)
{
delete ptr;
}
}
}
}