首页 新闻 会员 周边 捐助

c++多线程中,智能指针shared_ptr的同步问题

0
悬赏园豆:20 [待解决问题]

编写了一个支持多线程的无锁队列,但是在多线程读写的时候,遇到了奇怪的问题:
假设tail_所指节点存储的初始初始为0(以下缩略),线程1将tail_更新四次,使tail_更新为4,这时,线程2执行 std::shared_ptr<node> old_tail = std::atomic_load(&tail_);
结果old_tail仍为0,且在线程2中,tail_仍为0,请问这是为什么,如何解决?
代码如下:
template <class T>
class lock_free_queue
{

public:
lock_free_queue()
{
tail_ = std::make_shared<node>();
head_ = tail_;
}
void push(T e)
{
std::shared_ptr<node> new_node = std::make_shared<node>();
new_node->data = e;
std::shared_ptr<node> old_tail = std::atomic_load(&tail_);

    do
    {
        while (old_tail->next) {
            std::atomic_compare_exchange_weak(&tail_, &old_tail, old_tail->next);
            old_tail = std::atomic_load(&tail_);
        }
    } while (!std::atomic_compare_exchange_weak(&old_tail->next,&new_node->next ,new_node));
    std::atomic_compare_exchange_weak(&tail_, &old_tail, new_node);

}

bool pop(T &q)
{
    int i=0;
    std::shared_ptr<node> old_head;
    std::shared_ptr<node> old_tail;
    while (1)
    {
        old_head = std::atomic_load(&head_);
        old_tail = std::atomic_load(&tail_);
        if (old_head == head_) 
        {
            if (!old_head->next)
            {
                if (++i < 10)
                {
                    Sleep(0);
                    continue;
                }
                return false;
            }
            if (old_head == old_tail&&old_head->next)
            {
                std::atomic_compare_exchange_weak(&tail_, &old_tail, old_head->next);
            }
            if (std::atomic_compare_exchange_weak(&head_, &old_head, old_head->next))
            {
                q = old_head->next->data;
                std::cout << q<<std::endl;
                return true;
            }
        }
    }
}


struct node
{
    T data;
    std::shared_ptr<node> next;

    //node(const T& data_) : data(std::make_shared<T>(data_)) {}
};

private:
std::shared_ptr<node> head_;
std::shared_ptr<node> tail_;
};

pwh辉哥的主页 pwh辉哥 | 初学一级 | 园豆:182
提问于:2019-12-23 10:58
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册