C++ 我应该在FIFO排队中添加内存屏障吗?

C++ 我应该在FIFO排队中添加内存屏障吗?,c++,multithreading,fifo,memory-barriers,C++,Multithreading,Fifo,Memory Barriers,我正在使用链表实现一个非锁定FIFO FIFO的排队基本上是: void Enqueue(CNode node) { m_tail->m_next = node; // Do I need a memory barrier here? m_tail = node; } 我想知道如果它是单线程的,是否需要添加内存屏障(例如,编译器/处理器是否可以重新排列上面两行的顺序?)。如果它是多线程的(即,像单读单写器一样简单),该怎么办 编辑:根据,这是一种数据反依赖的情况,语句不应

我正在使用链表实现一个非锁定FIFO

FIFO的
排队
基本上是:

void Enqueue(CNode node)
{
  m_tail->m_next = node;

  // Do I need a memory barrier here?

  m_tail = node;
}
我想知道如果它是单线程的,是否需要添加内存屏障(例如,编译器/处理器是否可以重新排列上面两行的顺序?)。如果它是多线程的(即,像单读单写器一样简单),该怎么办


编辑:根据,这是一种数据反依赖的情况,语句不应重新排序。所以我假设CPU应该总是按照给定的顺序访问内存。是这样吗?

编译器不能重新安排m_tail和m_tail->next赋值,这样m_tail在设置m_tail->next之前就被分配给节点。但是,对于多线程解决方案,您可能需要担心:

temp = m_tail;
m_tail = node;
temp->next = node;
node->next = NULL; 

使用内存屏障,编译器和/或处理器必须完成
m_tail->next=节点m_tail=node之前,代码>(和
node->next=NULL;
。这是否足以保证正确执行还不确定,这在一定程度上取决于另一端的代码读取功能

我怀疑你的代码已经不是线程安全的了。如果线程在这两条语句之间暂停任意时间,会发生什么情况?另一个线程进入并覆盖您的工作是否安全?一半没有另一半有意义吗?无锁列表更新通常在某个地方有一个CAS循环。@GManNickG,我提到了关于多线程,我的意思是“单读单写”。@EricZ:我的观点仍然有效。语句之间的状态可以使用吗?@GManNickG,如果你的意思是读卡器可以同时更新同一个节点,不,那不是我的问题。我添加了一个sentinel节点,以防止读写器同时访问同一个节点。但是,无论如何,我关心的是,如果编译器/CPU会重新排序这两个语句,那么它们什么时候会重新排序。即使编译器没有重新排列这两个赋值的顺序,是否可以保证其他线程看到按该顺序进行的赋值?它们可能运行在不同的内核上,本地缓存没有以相同的顺序更新,等等。或者这种可能性可以以某种方式排除吗?数据依赖项将以相同的顺序获取CPU提交内存访问。这是真的吗?现代编译器和现代CPU按照“对它们有意义”的顺序进行操作。例如,处理器将无序执行指令,因为数据是如何从内存中提取的。Compile可能会发现以不同的方式使用寄存器会使代码更高效。我承认,上面的例子并不常见,但根据寄存器中的内容(以及“空闲”的寄存器数量),编译器可能会决定重新安排存储和加载,以提高寄存器的使用率。考虑CNode和Enqueue的构造函数是内联的…