• 无锁栈的实现


    template<typename T>
    class LockFreeStack
    {
    private:
        struct Node;
        
        struct CountedNode
        {
            int   externalCount = 0;
            Node* ptr           = nullptr;
        };
        
        struct Node
        {
            std::shared_ptr<T> data;
            std::atomic<int>   internalCount;
            CountedNode        next;
            
            Node(T const& data_):
                data(std::make_shared<T>(data_)),
                internalCount(0)
            {}
        };
        
        std::atomic<CountedNode> head;
        
        void increaseHeadCount(CountedNode& oldCounter)
        {
            CountedNode newCounter;
            do {
                newCounter = oldCounter;
                ++newCounter.externalCount;
            } while (!head.compare_exchange_strong(oldCounter, newCounter,
                                                   std::memory_order_acquire,
                                                   std::memory_order_relaxed));
            oldCounter.externalCount = newCounter.externalCount;
        }
    public:
        ~LockFreeStack()
        {
            while(pop() != nullptr);
        }
        
        void push(T const& data)
        {
            CountedNode newNode;
            newNode.ptr = new Node(data);
            newNode.externalCount = 1;
            newNode.ptr->next = head.load(std::memory_order_relaxed);
            while(!head.compare_exchange_weak(newNode.ptr->next, newNode,
                                              std::memory_order_release,
                                              std::memory_order_relaxed));
        }
        
        std::shared_ptr<T> pop()
        {
            auto oldHead = head.load(std::memory_order_relaxed);
            for(;;){
                increaseHeadCount(oldHead);
                auto const nodePtr = oldHead.ptr;
                
                if (nodePtr == nullptr){
                    return shared_ptr<T>();
                }
                
                if (head.compare_exchange_strong(oldHead, nodePtr->next,
                                                 std::memory_order_relaxed)){
                    std::shared_ptr<T> result;
                    result.swap(nodePtr->data);
                    int const increaseCount = oldHead.externalCount - 2;
                    if (nodePtr->internalCount.fetch_add(increaseCount,
                                                         std::memory_order_release)
                        == -increaseCount){
                        delete nodePtr;
                    }
                    return result;
                }
                else if (nodePtr->internalCount.fetch_add(-1,
                                                std::memory_order_acquire) == 1){
                    nodePtr->internalCount.load(std::memory_order_acquire);
                    delete nodePtr;
                }
            }
        }
    };

    为了测试其正确性,我用了以下代码作为实验:

        LockFreeStack<int> stack;
        std::thread t1([&]
                       {
                           for (int i = 0; i < 100; ++i){
                               if(i % 2 == 0){
                                   stack.push(i);
                               }
                               else{
                                   auto const result = stack.pop();
                                   if (result != nullptr){
                                       cout << *result << " ";
                                   }
                               }
                           }
                       });
        std::thread t2([&]
                       {
                           for (int i = 100; i < 200; ++i){
                               stack.push(i);
                           }
                       });
        std::thread t3([&]
                       {
                           for (int i = 0; i < 199; ++i){
                               auto const result = stack.pop();
                               if (result != nullptr){
                                   cout << *result << " ";
                               }
                           }
                       });
        t1.join();
        t2.join();
        t3.join();

    结果输出很奇怪,很多好多上千的数,我一度认为是栈实现的问题,直到我用 printf 替换了 cout 之后……

  • 相关阅读:
    Eclipse安装SVN插件(转载)
    推荐eclipse插件Properties Editor(转)
    Eclipse快捷键(转载)
    添加路由命令
    oracle 随机数(转载)
    《图解CSS3——第1章 揭开CSS3的面纱》
    css高度自适应
    JS生成随机数
    判断IE浏览器版本
    IE下SCRIPT5009: “JSON”未定义
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4855274.html
Copyright © 2020-2023  润新知