我一直在想这两个函数的返回值。 __sync_bool_compare_and_swap函数的返回值似乎具有明显的优点,即我可以使用它来判断是否发生交换操作。但是,我无法看到__sync_val_compare_and_swap的返回值的良好用法。__sync_val_compare_and_swap vs __sync_bool_compare_and_swap
首先,让我们有参考函数签名(从GCC文档减去VAR参数):
type __sync_val_compare_and_swap (type *ptr, type oldval type newval);
我看到的问题是,__sync_val_compare_and_swap的返回值是* PTR的旧值。确切地说,一旦实施适当的记忆障碍后,实施这项功能就可以看到它的价值。我明确声明了这一点,以迎合调用__sync_val_compare_and_swap和执行指令来强制执行内存屏障的事实,* ptr的值可以轻易改变。
现在,当函数返回我可以做什么与返回值?试图将它与* ptr进行比较没有意义,因为现在可以在其他线程上更改* ptr。同样,比较newval和* ptr也不能真正帮助我(除非我锁定* ptr,这可能首先破坏我对原子的使用)。
因此,我真正要做的是询问返回值== oldval是否有效(请参阅下面的警告)询问是否进行交换操作。所以我可以使用__sync_bool_compare_and_swap。
我刚刚提到的警告是,我可以在这里看到的唯一细微差别是,这样做并不告诉我交换是否发生,它只是告诉我,在内存屏障释放之前的某个点* ptr与newval具有相同的值。我正在考虑oldval == newval的可能性(尽管我很难看到一种有效实现函数的方式,以便它可以首先检查这些值,如果它们相同,则不交换,因此可能是一个争论点)。然而,我不能看到知道这种差异会在呼叫站点对我造成影响的情况。事实上,我无法想象一种情况,我会设置oldval和newval是平等的。
我的问题是这样的:
有没有在使用__sync_val_compare_and_swap和__sync_bool_compare_and_swap不会是等同的任何使用情况下,即是有一个地方提供比其他更多信息的情况吗?
ASIDE
我在想这样做的原因是,我发现__sync_val_compare_and_swap的实施sync_bool_compare_and_swap方面具有种族:
inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval)
{
int32_t ret = *ptr;
(void)__sync_bool_compare_and_swap(ptr, oldval, newval);
return ret;
}
这场比赛是对的存储* ptr在ret中,因为在调用__sync_bool_compare_and_swap之前* ptr可能会改变。它让我意识到,在sync_bool_compare_and_swap方面实现__sync_val_compare_and_swap似乎并不是一种安全的方式(没有额外的障碍或锁定)。这让我想到前者必须提供比后者更多的“信息”,但根据我的问题,我没有看到它确实如此。
一种用法:返回的当前值可用于重试。我知道有原子增量,但为了说明目的,假设你想实现这个。您可以简单地使用oldvalue作为前增量和新值作为前增量来调用val_compare_and_swap。如果成功,你就完成了。如果不是,则可以通过递增返回的值并再次调用val_compare_and_swap来重试。使用bool版本,您需要额外读取当前的重试值。 – kaylum
你是对的,你的“旁边”的代码是越野车/有严重的竞争条件。需要重试循环才能使其正确。看到我的答案。 –