c++ - 我可以在单读/单写队列中用 volatile 替换原子吗?

标签 c++ multithreading atomic volatile happens-before

让我们考虑以下用链表实现的单读/单写队列。

struct queue {
  queue() {
    tail = head = &reserved;
    n = 0;
  }
  void push(item *it) {
     tail->next = it;
     tail = it;
     n++;
  }
  item* pop() {
     while (n == used);
     ++used;
     head = head->next;
     return head;
  }

  item reserved;
  item *tail, *head;

  int used = 0;
  std::atomic <int> n;
}

现在我发现使用 volatile int n可以让我的作家跑得更快,虽然我不确定它是否能保证 head = head->next始终可以读取正确的值。

更新:如果在 tail->next 之间添加原子操作会怎样, n++ , IE。,

void push(item *it) {
   tail->next = it;
   tail = it;
   a.store(0, std::memory_order_release);
   a.load(std::memory_order_acquire);
   n++;
}

其中a永远不会被读者访问?这会保证tail->next = it的顺序吗?和 head = head->next ? (不过,它比使用原子 n 运行得更快)

最佳答案

volatile C++ 中的关键字不是一种结构,可以保证变量读/写在多线程环境中按照代码中的顺序排列。所以,在你的代码中,原子模板包装的计数器被 volatile 暴露了出来。仅关键字,消费者线程观察到的计数器的增加并不能保证 item::next也已更新。

为了在保证的情况下实现最大性能,我认为至少您必须在更新 head->next 之间插入一个写屏障。以及到柜台的增量,例如来自 n.fetch_add(1, std::memory_order_release) ,以及在获取 tail->next 之前的读取屏障, 喜欢 n.load(std::memory_order_acquire) .不过,我不知道 CPU-arch 的具体细节。

关于c++ - 我可以在单读/单写队列中用 volatile 替换原子吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60292848/

相关文章:

java - JDBC 通过 PreparedStatement 中的 executeBatch 调用保证原子操作

c++ - 如何获取安装在 Windows 7 中的主题列表(主题名称)?

c++ - Qt编程——QtConcurrence kill线程

c++ - 理解 std::fmod 和 std::remainder

multithreading - TClientSocket和线程

java - Java 中的并发性 : synchronized static methods

c - 简单赋值运算符的原子性

multithreading - 交换的替代版本!还返回换出的值(value)

c++ - CreateProcess只执行一半命令

c++ - TFTP 服务器没有从客户端接收