C ++ 11对atomic variables进行了“比较和交换”操作。
语义是:
以原子方式将
obj
指向的值与expected
指向的值进行比较,如果相等,则将前者替换为desired
(执行读 - 修改 - 写操作)。否则,将obj
指向的实际值加载到*expected
(执行加载操作)。
我想做同样的事情,但是当值相等时我不想设置*obj
,而是希望当一个大于另一个时设置它(假设我们'重新谈论有序的类型。)
这是以某种方式支持的吗?也许可以通过一些黑客实现?
注意: CAS循环不适用于我,因为我正在比较的两个值可能会在非原子操作之间发生变化。
答案 0 :(得分:7)
我认为你误解了比较和交换/交换是如何工作的:基本的想法是,看了当前值,你可以计算出一些相应的新值 - 然后你尝试更新。如果它成功 - 很好 - 继续你需要的任何东西,但如果它失败然后重新开始:查看其他线程放在那里的新值并考虑你现在需要的价值。
我希望在一个大于另一个时设置它(假设我们正在谈论一个有序类型)。
所以说你想要存储11但是只有当现有值仍然小于11时才会存储。你不会直接找到这样做的指令,但你可以用现有的比较和交换轻松完成:
int target_value = 11;
do {
int snapped_x = x;
if (snapped_x >= target_value)
what do you want to do instead?
} while (!compare_and_swap(x, snapped_x, target_value));
// ...or whatever your exact calling convention is...
你仍然可以得到你想要的行为,只是潜在的更高的失败/旋转率....
答案 1 :(得分:5)
根据要求,这是我的评论作为答案:
我也希望这存在,但据我所知(当然不适用于x86 / x64),除了概念上,当然还有(可能)使用多个原子指令的变通方法(哪些工作但不等待)。
答案 2 :(得分:-1)
这可能是一个古老的问题,但是我认为许多人会想要这种功能。 我想出了一个主意,在这里显示伪代码(我是linux内核的人,所以要使用一些内核函数)。
update(new)
{
old = atomic_read(&pvalue);
while (old < new) {
v = atomic_cmpxchg(&pvalue, old, new);
if (v != old) {
old = v;
continue;
}
}
}
对于旧值小于新值的代码,不会尝试使用cmpxchg。
如果有并发问题,请告诉我。谢谢:)