【发布时间】:2012-10-05 23:02:51
【问题描述】:
我想使用原子比较和交换,但不是等于,我只想在内存位置不等于旧值时进行交换。 C语言可以吗?
【问题讨论】:
标签: c multithreading gcc compare-and-swap
我想使用原子比较和交换,但不是等于,我只想在内存位置不等于旧值时进行交换。 C语言可以吗?
【问题讨论】:
标签: c multithreading gcc compare-and-swap
这个怎么样:
void compare_and_swap_if_not_equal(word_t const required_non_value, word_t const new_value, word_t* ptr_to_shared_variable) {
for (;;) {
word_t const snapshot_value = *ptr_to_shared_variable;
if (required_non_value == snapshot_value) {
break;
// or (sleep and) 'continue;', if you want to wait for the stored value to be different
// -- but you might of course miss a transient change to a different state and back.
} else {
if (compare_and_swap_if_equal(ptr_to_shared_variable, snapshot_value, new_value)) {
// we know the stored value was different; if this 'theory' still matches reality: swap! done!
break;
}
}
}
}
未经测试。未编译。使用'const'是因为我喜欢这样:)。 'word_t' 是一个类型占位符,我不知道真正的类型应该是什么。而且我不知道在 stdatomic.h 中如何调用“compare_and_swap_if_equal”。
(添加) atomic_compare_exchange_weak() 是票。出于某种原因,它需要一个指向“预期”参数的指针,因此您必须将上面的代码修改为
如果 (atomic_compare_exchange_weak(ptr_to_shared_variable, &snapshot_value, new_value)) ...
“弱”版本应该在上面的代码中工作;虚假地返回“false”只会在循环中增加另一个行程。仍未编译,未经测试;不要在家里依赖这个代码。
【讨论】:
snapshot_value 和原子 cas 之间变化怎么办?似乎循环永远不会结束。此外,在获取指针之前我们不需要内存屏障吗? (原子 cas 暗示它)
这取决于你的架构,但一般来说,在 C 中是不可能做到这一点的。
通常,比较和交换是通过从内存中的某个位置自动加载的指令实现的,如果内存中的位置与您指定的某个现有值匹配,则将值存储到该位置。
至少在 x86 上没有规定仅在值不匹配时才执行此加载。也不清楚你为什么想做这样的事情。也许另一种架构会支持这样的东西,但这将取决于架构,而不是可以在 C 中以可移植方式完成的事情。
【讨论】:
xchg 指令正是 OP 想要的,无条件的原子交换。