大于比较和交换

正如标题所示,我正在寻找一个比较和交换的实现,但比比较更大:

if(newValue > oldValue) {
    oldValue = newValue;
}

其中 是某个全局共享状态,并且是每个线程的私有状态,而不这样做:oldValuenewValue

synchronized(locker) {
    if(newValue > oldValue) {
        oldValue = newValue;
    }       
}

因为我想要一个非阻塞解决方案。通过研究其他非阻塞操作的源代码,我得出了这个(假设值是整数):

AtomicInteger oldValue; // shared global variable

...

public boolean GreaterThanCAS(int newValue) {

    while(true) {
        int local = oldValue;
        if(local == oldValue) {
            if(newValue > local) {
                 if(oldValue.compareAndSet(local, newValue) {
                     return true;  // swap successful
                 } // else keep looping
            } else {
                 return false; // swap failed
            }
        } // else keep looping
    }
}

当发生时,这意味着另一个线程在此期间更改了,所以我需要循环并重试。// else keep loopingoldValue

此实现是否正确(线程安全)?


答案 1

从Java 8开始,这可以通过使用updateAndGet来简化:

public boolean greaterThanCAS(int newValue) {
    return oldValue.updateAndGet(x -> x < newValue ? newValue : x) == newValue;
}

请注意,如果新旧值相等,这也将返回 true。如果这不是想要的行为,请尝试@Adam的答案


答案 2

我认为您的实现没有问题,前提是没有线程会降低AtomicInteger的值。如果他们这样做,您的代码将对竞争条件开放。

请注意,代码可以简化如下:

public boolean GreaterThanCAS(int newValue) {
    while(true) {
        int local = oldValue.get();
        if(newValue <= local) {
             return false; // swap failed
        }
        if(oldValue.compareAndSet(local, newValue)) {
             return true;  // swap successful
        }
        // keep trying
    }
}