加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 使用boost :: atomic的无锁队列 – 我这样做了吗?

发布时间:2020-12-16 06:59:01 所属栏目:百科 来源:网络整理
导读:精简版: 我试图从here替换无锁,单生成器,单消费者队列实现中使用的C 11中的std :: atomic.如何用 boost::atomic 替换它? 长版: 我正试图通过工作线程从我们的应用程序中获得更好的性能.每个线程都有自己的任务队列.我们必须在出列/排队每个任务之前使用锁
精简版:

我试图从here替换无锁,单生成器,单消费者队列实现中使用的C 11中的std :: atomic.如何用boost::atomic替换它?

长版:

我正试图通过工作线程从我们的应用程序中获得更好的性能.每个线程都有自己的任务队列.我们必须在出列/排队每个任务之前使用锁同步.

然后我找到了Herb Sutter关于无锁队列的文章.这似乎是一个理想的替代品.但代码使用了C 11中的std :: atomic,目前我无法将其引入到项目中.

更多的谷歌搜索导致了一些例子,例如this one for Linux (echelon’s)和this one for Windows (TINESWARE’s).两者都使用平台的特定构造,如WinAPI的InterlockedExchangePointer和GCC的__sync_lock_test_and_set.

我只需要支持Windows& Linux也许我可以逃脱一些#ifdefs.但我认为使用boost :: atomic提供的东西可能更好. Boost Atomic尚未成为官方Boost库的一部分.所以我从http://www.chaoticmind.net/~hcb/projects/boost.atomic/下载了源代码并在我的项目中使用了包含文件.

这是我到目前为止所得到的:

#pragma once

#include <boost/atomic.hpp>

template <typename T>
class LockFreeQueue
{
private:
    struct Node
    {
        Node(T val) : value(val),next(NULL) { }
        T value;
        Node* next;
    };
    Node* first; // for producer only
    boost::atomic<Node*> divider;  // shared
    boost::atomic<Node*> last; // shared

public:
    LockFreeQueue()
    {
        first = new Node(T());
        divider = first;
        last= first;
    }

    ~LockFreeQueue()
    {
        while(first != NULL) // release the list
        {
            Node* tmp = first;
            first = tmp->next;
            delete tmp;
        }
    }

    void Produce(const T& t)
    {
        last.load()->next = new Node(t); // add the new item
        last = last.load()->next;
        while(first != divider) // trim unused nodes
        {
            Node* tmp = first;
            first = first->next;
            delete tmp;
        }
    }

    bool Consume(T& result)
    {
        if(divider != last) // if queue is nonempty
        {
            result = divider.load()->next->value; // C: copy it back
            divider = divider.load()->next;
            return true;  // and report success
        }
        return false;  // else report empty
    }
};

需要注意的一些修改:

boost::atomic<Node*> divider;  // shared
boost::atomic<Node*> last; // shared

last.load()->next = new Node(t); // add the new item
    last = last.load()->next;

result = divider.load()->next->value; // C: copy it back
        divider = divider.load()->next;

我是否正确地在boost :: atomic中应用了load()(以及隐式store())?我们可以说这相当于Sutter原来的C 11无锁队列吗?

PS.我在SO上研究了许多线程,但似乎没有一个提供boost :: atomic& amp;无锁队列.

解决方法

你试过 Intel Thread Building Blocks’原子< T>?跨平台和免费.

也…

单个生产者/单个消费者使您的问题更容易,因为您的线性化点可以是单个运算符.如果您准备接受有界队列,它会变得更容易.

有界队列提供缓存性能的优势,因为您可以保留缓存对齐的内存块以最大化您的命中,例如:

#include <vector>
#include "tbb/atomic.h"
#include "tbb/cache_aligned_allocator.h"    

template< typename T >
class SingleProdcuerSingleConsumerBoundedQueue { 
    typedef vector<T,cache_aligned_allocator<T> > queue_type;

public:
    BoundedQueue(int capacity):
        queue(queue_type()) {
        head = 0;
        tail = 0;
        queue.reserve(capacity);
    }

    size_t capacity() {
        return queue.capacity();
    }

    bool try_pop(T& result) {
        if(tail - head == 0)
            return false;
        else {
            result = queue[head % queue.capacity()];
            head.fetch_and_increment(); //linearization point
            return(true);
        }
    }

    bool try_push(const T& source) {
        if(tail - head == queue.capacity()) 
            return(false);
        else {
            queue[tail %  queue.capacity()] = source;
            tail.fetch_and_increment(); //linearization point
            return(true);
        }
    }

    ~BoundedQueue() {}

private:
    queue_type queue;
    atomic<int> head;
    atomic<int> tail;
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读