首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用std::C++11无锁队列(多写入器,单用户)

使用std::C++11无锁队列(多写入器,单用户)
EN

Stack Overflow用户
提问于 2013-12-20 18:57:14
回答 2查看 7.7K关注 0票数 5

我使用新的std::atomic在C++11中生成了一个无锁(无锁)队列的简单实现,我看不出我在这里做了什么。

代码语言:javascript
复制
#include <atomic>

template<typename T>
class lockless_queue
{
public:
    template<typename DataType>
    struct node
    {
        node(const DataType& data)
          : data(data), next(nullptr) {}
        DataType data;
        node* next;
    };

    lockless_queue()
      : head_(nullptr) {}

    void produce(const T &data)
    {
        node<T>* new_node = new node<T>(data);
        // put the current value of head into new_node->next
        new_node->next = head_.load(std::memory_order_relaxed);
        // now make new_node the new head, but if the head
        // is no longer what's stored in new_node->next
        // (some other thread must have inserted a node just now)
        // then put that new head into new_node->next and try again
        while(!std::atomic_compare_exchange_weak_explicit(
            &head_,
            &new_node->next,
            new_node,
            std::memory_order_release,
            std::memory_order_relaxed)) {}
    }

    node<T>* consume_all()
    {
        // Reset queue and return head atomically
        return head_.exchange(nullptr, std::memory_order_consume);
    }
private:
    std::atomic<node<T>*> head_;
};

// main.cpp
#include <iostream>

int main()
{
    lockless_queue<int> s;
    s.produce(1);
    s.produce(2);
    s.produce(3);
    auto head = s.consume_all();
    while (head)
    {
        auto tmp = head->next;
        std::cout << tmp->data << std::endl;
        delete head;
        head = tmp;
    }
}

我的产出是:

代码语言:javascript
复制
2
1
Segmentation fault (core dumped)

我能有一些指点,看看哪里,或者指出我可能做错了什么?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-20 19:24:19

您正在取消tmp而不是head的引用。

代码语言:javascript
复制
while (head)
    {
        auto tmp = head->next;
        std::cout << tmp->data << std::endl;
        delete head;
        head = tmp;
    }

应:

代码语言:javascript
复制
while (head)
    {
        std::cout << head->data << std::endl;
        auto tmp = head->next;
        delete head;
        head = tmp;
    }

这就是为什么3没有出现在您的输出中,而Segmentation fault却出现在输出中。

票数 3
EN

Stack Overflow用户

发布于 2013-12-22 17:42:22

在您的代码中有另一个错误,除非您开始尝试执行并发的队列,否则不会出现。如果compare_exchange_weak_explicit失败,这意味着另一个线程设法更改了head指针,因此在您再次尝试head之前,需要将head指针的新值重新加载到new_node->next中。以下是其中的诀窍:

代码语言:javascript
复制
    while(!std::atomic_compare_exchange_weak_explicit(
        &head_,
        &new_node->next,
        new_node,
        std::memory_order_release,
        std::memory_order_relaxed)) {
        new_node->next = head_.load(std::memory_order_relaxed);
    }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20710243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档