13

C++11 对原子变量有一个“比较和交换”操作。

语义是:

原子地比较 所指向的值obj与 所指向的值expected,如果相等,则将前者替换为desired(执行读-修改-写操作)。否则,将指向的实际值加载到objinto *expected(执行加载操作)。

我想做同样的事情,但不是*obj在值相等时设置,而是在一个大于另一个时设置它(假设我们谈论的是有序类型)。

这是否以某种方式支持?也许可以通过一些黑客来实现?

注意: CAS 循环不适合我,因为我比较的两个值可能会在非原子操作之间发生变化。

4

3 回答 3

12

我认为您误解了比较和交换/交换的工作原理:基本思想是查看当前值后,您可以计算出一些相应的新值-然后尝试进行更新。如果它成功了 - 很好 - 继续你需要的任何东西,但如果它失败了,那就重新开始:查看其他线程放在那里的新值,并考虑你现在需要的值。

我希望在一个大于另一个时设置它(假设我们谈论的是有序类型)。

因此,假设您要存储 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...

你仍然可以得到你想要的行为,只是有可能更高的失败/旋转率......

于 2013-07-17T13:55:17.887 回答
5

根据要求,这是我的评论作为答案:


我也希望它存在,但据我所知(当然不适用于 x86/x64),当然,除了在概念上,以及(可能)使用多个原子指令的变通方法(有效但不是免等待)。

于 2013-07-18T21:43:51.170 回答
-1

这可能是一个老问题,但我想很多人会想要这种功能。我想出了一个主意,这里显示伪代码(我是linux内核的人,所以使用一些内核函数)。

update(new)
{
  old = atomic_read(&pvalue);
  while (old < new) {
    v = atomic_cmpxchg(&pvalue, old, new);
    if (v != old) {
      old = v;
      continue;
    }
  }
}

该代码不会尝试 cmpxchg 旧值小于新值。
如果有并发问题,请告诉我。谢谢:)

于 2020-01-16T16:05:36.090 回答