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;
}
开发者_如何学JAVA... 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.
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.
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.
精彩评论