Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用无锁指针队列在线程之间移动数据安全吗_C++_Multithreading_Concurrency - Fatal编程技术网

C++ 使用无锁指针队列在线程之间移动数据安全吗

C++ 使用无锁指针队列在线程之间移动数据安全吗,c++,multithreading,concurrency,C++,Multithreading,Concurrency,我已经实现了一个简单的循环缓冲区,使用()readerwriterqueue在线程之间移动数据,以防止(取消)应用程序中的分配。代码如下所示: using ElemPtr = std::unique_ptr<int>; moodycamel::ReaderWriterQueue<ElemPtr> emptyQueue(10); moodycamel::ReaderWriterQueue<ElemPtr> dataQueue(10); LoadQueueWith

我已经实现了一个简单的循环缓冲区,使用()
readerwriterqueue
在线程之间移动数据,以防止(取消)应用程序中的分配。代码如下所示:

using ElemPtr = std::unique_ptr<int>;
moodycamel::ReaderWriterQueue<ElemPtr> emptyQueue(10);
moodycamel::ReaderWriterQueue<ElemPtr> dataQueue(10);
LoadQueueWithPointers(emptyQueue);

//If statements removed for brevity
auto producer = [&]() {
    ElemPtr ptr;
    while (true) {
        emptyQueue.try_dequeue(ptr);
        LoadData(ptr);
        dataQueue.try_enqueue(std::move(ptr));
    }
};

//If statements removed for brevity
auto consumer = [&]() {
    ElemPtr ptr;
    while (true) {
        dataQueue.try_dequeue(ptr);
        ProcessData(ptr);
        emptyQueue.try_enqueue(std::move(ptr));
    }
};

std::thread producerThread(producer);
std::thread consumerThread(consumer);
使用ElemPtr=std::unique\u ptr;
moodycamel::ReaderWriterQueue emptyQueue(10);
moodycamel::ReaderWriterQueue数据队列(10);
LoadQueueWithPointers(emptyQueue);
//为简洁起见,删除了If语句
汽车生产者=[&](){
elemptrptr;
while(true){
清空队列。尝试退出队列(ptr);
载荷数据(ptr);
dataQueue.try_enqueue(std::move(ptr));
}
};
//为简洁起见,删除了If语句
汽车消费者=[&](){
elemptrptr;
while(true){
数据队列。尝试退出队列(ptr);
过程数据(ptr);
emptyQueue.try_enqueue(std::move(ptr));
}
};
标准:螺纹生产商螺纹(生产商);
std::线程使用者读取(使用者);
在检查这段代码时,在我看来,如果使用者线程在RAM中更新数据(指针引用的数据)之前接收到指针,那么数据可能会损坏。我试图通过延迟、不同队列长度、不同数据大小以及将线程移动到物理上分离的处理器(套接字)来诱导数据损坏。到目前为止,我还没有发现数据损坏问题


因此,我的问题是:
moodycamel::ReaderWriterQueue
使用的内存围栏(
std::memory\u order\u acquire
std::memory\u order\u release
)是否也能保护我的(非原子)内存操作;DR:只要
ReaderWriterQueue
的实现使用具有正确内存顺序的原子类型,就可以了

您需要的内存顺序是写入端的
memory\u order\u release
,以及读取端的
memory\u order\u acquire
。这些内存顺序意味着,原子写入之前的所有写入都需要首先发生,原子读取之后的所有读取都需要稍后发生。这些其他写/读操作包括访问
ElemPtr
s后面的数据


由于队列本身需要将数据从一个线程发送到另一个线程,因此它需要在自己的原子元数据上使用完全相同的内存顺序,以便能够发送有效负载数据指针。因此,如果正确实现了
ReaderWriterQueue
,您应该是安全的。

原子加载/存储的内存顺序存在,因为它们控制其他非原子加载/存储的重新排序方式。所以,据推测,你很好。但是,请注意,如果在强顺序CPU(如x86)上进行测试,那么CPU会隐藏许多潜在问题。因此,在另一个保证较弱的CPU(如ARM)上,您可能会遇到问题。