让我们考虑以下用链表实现的单读/单写队列。
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/