CompareExchange可以用CompareAndSwap来实现吗?

发布于 2024-08-25 16:29:58 字数 526 浏览 2 评论 0原文

假设 CompareAndSwap(或 CAS)永远不会意外失败,CompareExchange 可以用 CAS 实现吗?

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

使用 CompareExchange 实现 CAS 很简单:

int CompareExchange (int* p, int expected, int newvalue);

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

...但是可以使用 CAS 实现 CompareExchange 吗?我见过的所有尝试要么具有竞争条件,要么不保证无锁属性。我不相信这是可能的。

Assuming that CompareAndSwap (or CAS) never fails spuriously, can CompareExchange be implemented with CAS?

CompareExchange both take a pointer, an expected value, and a new value and atomically set the memory referenced by the pointer to the new value if it matches the expected value. The difference between the two is that CompareExchange returns the previous value of the memory area and CompareAndSwap returns a bool indicating success or failure.

It's trivial to implement CAS with CompareExchange:

int CompareExchange (int* p, int expected, int newvalue);

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

... but is it possible to implement CompareExchange with CAS? All the attempts I've seen either have race conditions or don't guarantee lockless properties. I don't believe it's possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

焚却相思 2024-09-01 16:29:58

我不明白这怎么可能。对于 CAS 失败的情况,您需要单独的操作来获取之前的值。这个单独的操作相对于 CAS 来说不是原子的。

您可以部分解决:

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

在您遇到问题的情况下,CAS 会失败。使用 *p 查找前一个值相对于 CAS 而言不是原子的,因此您要么存在竞争条件,要么必须锁定 CAS 和 *p 取消引用。

I don't see how it's possible. For the case where CAS fails, you'll need a separate operation to get the previous value. This separate operation will not be atomic relative to the CAS.

You can get part way there:

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

It's the case where CAS fails where you have the problems. Getting *p to find what the previous value is will not be atomic relative to CAS so you either have a race condition or you would have to lock around the CAS and the *p dereference.

半城柳色半声笛 2024-09-01 16:29:58

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

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 的修改与两个 if 之间的修改没有区别。

同样,你可以基于CAS实现原子交换和原子取操作,但它不会是免等待的。

You can, and it is lock-free, but it is not wait-free:

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

The idea is that a modification of *p after returning from CompareExchange is indistinguishable from a modification between the two ifs.

Similarly, you can implement atomic exchange and atomic fetch-and-OP based on CAS, but it will not be wait-free.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文