正确使用原子

Luc*_*MLI 4 c++ multithreading atomicity c++11

我写了一个基于向量的小型轻量级推/弹队列(想象它应该很快),如下所示:

template <typename T> class MyVectorQueue{

public:

    MyVectorQueue (size_t sz):my_queue(sz),start(0),end(0){}

    void push(const T& val){
       size_t idx=atomic_fetch_add(&end,1UL);
       if (idx==my_queue.size())
          throw std::runtime_error("Limit reached, initialize to larger vector");
       my_queue[idx]=val;
    }

    const T& pop(){
        if (start==end) 
           return end__;
        return my_queue[start.fetch_add(1UL)];
    }

    size_t empty()
    {
        return end==start;
    }

    const T& end() {
        return end__;
    }

private:
    T end__;
    std::atomic<size_t> start,end;
    std::vector<T> my_queue;    
}; 
Run Code Online (Sandbox Code Playgroud)

矢量的大小应该是已知的,我想知道为什么它不是线程安全的?在什么情况下这会弄乱我的结构?

Kir*_*rov 6

startend原子变量,但使用std::vector::operator[]不是原子操作,使其不是线程安全的.


假设您有10个线程,并且大小vector为5.现在,假设它们都在执行,比如说push.

现在假设所有10个线程都已经通过了检查,并且if (end==my_queue.size())被评估为false,并且end尚未达到限制,这意味着 - vector未满.

然后,所有这些都可能会增加end并同时调用std::vector::operator[].至少有5个线程将​​尝试访问向量"外部"的元素.