C++ 原子交换与大于而不是等于?

C++ 原子交换与大于而不是等于?,c++,c++11,atomic,compare-and-swap,C++,C++11,Atomic,Compare And Swap,C++11对具有“比较和交换”操作 语义是: 将obj指向的值与预期的指向的值进行原子比较,如果两者相等,则将前者替换为所需的(执行读-修改-写操作)。否则,将obj指向的实际值加载到*预期值中(执行加载操作) 我也希望这样做,但不是在值相等时设置*obj,而是在一个值大于另一个值时设置它(假设我们讨论的是有序类型) 这是否得到了某种支持?也许可以通过一些黑客来实现 注意:CAS循环不适合我,因为我正在比较的两个值可能会在非原子操作之间发生变化。我认为您误解了比较和交换/交换的工作原理:基本思想

C++11对具有“比较和交换”操作

语义是:

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

我也希望这样做,但不是在值相等时设置
*obj
,而是在一个值大于另一个值时设置它(假设我们讨论的是有序类型)

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


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

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

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

假设您想要存储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...

您仍然可以获得所需的行为,只是可能会有更高的故障/旋转率……

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



一、 我也希望它存在,但据我所知(当然不是x86/x64),除了概念上的,以及(可能)使用不止一条原子指令(可以工作但不是无等待)的变通方法之外,它没有。这可能是一个老问题,但我想很多人会想要这种功能。 我想到了一个主意,这里展示了伪代码(我是linux内核的人,所以使用一些内核函数)

更新(新)
{
old=原子读取(&p值);
while(旧<新){
v=原子值(旧值和新值);
如果(v!=旧){
old=v;
继续;
}
}
}
对于旧值小于新值的值,代码不会尝试cmpxchg。

如果有并发问题,请告诉我。谢谢:)

在循环中执行此操作非常简单,我相信很快会有人向您提供详细信息,但请告诉我,您希望如何使用此操作?您可以执行CAS循环,如。这可能是重复的,如果我理解正确的话。可能是重复的您的意思是obj是指向有序对象的指针,您想根据您指向的两个对象的比较结果设置指针吗?如果是:这是不可能的,因为CAS只处理一个内存地址。您的请求至少涉及两个内存地址:指针变量的地址(您要交换的对象)和您要比较的数据的地址。我也希望存在这样的地址,但它不存在(当然,除了概念上和(可能)使用多个原子指令的变通方法).这对我没什么帮助,因为在循环中执行每个原子指令后,我的目标值都会改变。所以呢?只是把重新计算它的指令放在“你想做什么”语句中…这没有帮助。一旦我达到while条件,
target_value
就不再是“改为做什么”语句中的值了。为什么不是呢?“改为做什么”语句后面紧跟着
while
条件。。。您完全控制
目标值
变量。我无意粗鲁,但要么我们在沟通上存在巨大分歧(我正努力寻找解释),要么我应该找另一个职业,或者,您完全无法了解CAS是如何工作的,也许应该看看一些简单的实现,比如递增计数器-确保它们能够进入…?也许值得一提的是,设置目标值并不意味着您希望CAS启动时目标值仍然有效。。。整点是当前值
snaped_x
和目标值之间的关系,这样,如果另一个线程没有更改
snaped_x
,则可以确保目标仍然有效。如果
snaped_x
发生更改,您将重新计算目标。。。
update(new)
{
  old = atomic_read(&pvalue);
  while (old < new) {
    v = atomic_cmpxchg(&pvalue, old, new);
    if (v != old) {
      old = v;
      continue;
    }
  }
}