代码之家  ›  专栏  ›  技术社区  ›  Dan Olson

CompareExchange可以用CompareAndSwap实现吗?

  •  1
  • Dan Olson  · 技术社区  · 14 年前

    假设compareAndSwap(或cas)从未出现错误的失败,CompareExchange能否与cas一起实现?

    CompareExchange都接受一个指针、一个预期值和一个新值,如果指针引用的内存与预期值匹配,则自动将其设置为新值。两者的区别在于,CompareExchange返回内存区域的前一个值,CompareAndSwap返回一个bool,指示成功或失败。

    使用CompareExchange实现CA很简单:

    int CompareExchange (int* p, int expected, int newvalue);
    
    bool CAS (int* p, int expected, int newvalue)
    {
       return CompareExchange (p, expected, newvalue) != expected;
    }
    

    …但是是否可以实现与CA的CompareExchange?我看到的所有尝试要么有比赛条件要么不保证无锁财产。我不相信这是可能的。

    2 回复  |  直到 13 年前
        1
  •  3
  •   R Samuel Klatchko    14 年前

    我不知道怎么可能。对于cas失败的情况,需要单独的操作来获取前一个值。这个单独的操作不会是相对于CAS的原子操作。

    你可以从那里得到一部分:

    int CompareExchnage(int *p, int expected, int newvalue)
    {
        if (CAS(p, expected, newvalue))
            return expected;
        else
            ???;
    }
    

    如果你有问题,CAS就会失败。得到 *p 要查找上一个值是什么,相对于cas,它不是原子的,因此您要么有争用条件,要么必须锁定cas和 *P 取消引用。

        2
  •  2
  •   Paolo Bonzini    13 年前

    您可以,而且它是免锁的,但它不是免等待的:

    int CompareExchange(int *p, int expected, int newvalue)
    {
        for (;;) {
            oldValue = *p;
            if (oldValue != expected)
                return oldValue;
            if (CAS(p, expected, newvalue))
                return expected;
        }
    }
    

    其想法是,从CompareExchange返回后对*P的修改与两个IFS之间的修改是不可区分的。

    同样,您可以基于CA实现原子交换和原子获取和操作,但它不会是无等待的。