为什么我的std :: atomic :: compare_exchange_weak实现了堆栈崩溃?

时间:2016-12-07 02:53:33

标签: multithreading c++11 thread-safety

我试图使用c ++ 11原子类编写一个简单的线程安全堆栈。 这些是我到目前为止所做的。

    void pushNode(Node* node) {
//
//      node->_next = _head.load(std::memory_order_relaxed);
//      while(!_head.compare_exchange_weak(node->_next, node));
//
// http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange
// Note: the above use is not thread-safe in at least
// GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899)
// MSVC prior to 2014-03-17 (bug 819819). The following is a workaround:
        Node* head = _head.load(std::memory_order_relaxed);
        do {
            node->_next = head;
        } while(!_head.compare_exchange_weak(head, node,
                            std::memory_order_release, std::memory_order_relaxed));
    }

    Node* popNode() {
        Node* head;
        Node* expected = _head.load(std::memory_order_relaxed);
        do {
            head = expected;
        } while(head && !_head.compare_exchange_weak(expected, head->_next,
                            std::memory_order_release, std::memory_order_relaxed));
        if(head)
            head->_next = nullptr;
        return head;
    }

    void pop() {
        delete popNode();
    }

private:
    std::atomic<Node*> _head;

我还编写了一个测试用例,以了解这个堆栈在某些条件下的稳定性(3个线程,每个线程随机提交一百万次推送和弹出操作)。答案并不多。

测试用程序崩溃了一段时间,引发访问冲突异常,读取0xbaadf00d 0xfeeefeee 0xcdcdcdcd或其他一些无效的内存地址。

经过几天的谷歌搜索,我发现的唯一可能导致此问题的是Is std::atomic_compare_exchange_weak thread-unsafe by design。正如在代码中评论的那样,我在这里找到了一个workround std::atomic::compare_exchange_weak。不知道ms家伙是否在我的编译器(MSVC 2015社区)中摆脱了这个错误的实现,我只是应用了workround补丁。

但是没有出现魔法,测试用例像往常一样崩溃。

std :: atomic :: compare_exchange_weak是否仍然被错误地实现,或者我只是做了一些愚蠢的事情?

0 个答案:

没有答案