[jboss-dev] compareAndSet variation

Andrew Dinn adinn at redhat.com
Wed Feb 10 11:40:53 EST 2010


On 02/10/2010 03:40 PM, David M. Lloyd wrote:
 > This doesn't really make any sense - you're saying if the value is
 > different, return the delta and leave the value unchanged, but if the 
delta
 > was zero between the expect and update, then the value wouldn't need
 > changing anyway!  You can do that with just a read.
I agree the request is not clear but I think I understand what is being 
asked for.  Assuming this is a methof of AtomicLong which has a long 
field called 'value' what would make sense would be:

   int compareAndSet(long expected, long new)
   atomic {
     if value == expected {
       value = new;
       return 0;
     else
       return value - expected;
     endif
   }

or, equivalently, in a form which clarifies the motive for the request:

   int compareAndSet(long expected, long new)
   atomic {
     int result = value - expected;
     if (result == 0) {
       value = new
     endif
     return result;
}

In other words can the update be conditional on the outcome of a 
subtract returning zero while the operation returns the value of the 
subtract operation whether or not the update occurs? This makes clear 
the difference form a normal CAS


   boolean compareAndSet(long expected, long new)
   atomic {
     boolean result = (value != expected);
     if (!result) {
       value = new
     endif
     return result;
}

Well, you could always implement this using conventional locking (which 
you can already do anyway) but you could not implement it using either a 
conventional hardware CAS instruction or LOAD_LINK STORE_CONDITIONAL 
pair. These only output a true or false result. So, when they succeed 
you know what the result of the subtract would be (zero) but when they 
fail you don't have enough information to identify the result as it was 
at the point where the check failed. n.b. reading value before or after 
trying an update with the CAS/LOAD_L-STORE_C is no good as the value is 
volatile. For example, reading after the CAS failed risks returning zero 
if some other thread updates the value to expected between the CAS and 
the read without actually updating value to new.

Building hardware which returned a difference rather than a boolean 
would be quite simple to do but no one has -- and almost certainly for 
good reasons. Since the updated value is by definition volatile the 
result of the subtraction is probably of no more use to you than the 
boolean result. If it is zero it tells you the value was as you expected 
and your update succeeded. If it is non-zero then you would need some 
very clever scheme to be usefully employ the result.

For example, imagine every thread which used this operation employed a 
unique positive integer as a lock value with 0 used to mean that the 
location was not locked. Supplying 0 as the expected value when 
attempting a lock operation would allow a non-zero return value to 
identify the lock owner _at the time of the lock attempt_. That might be 
useful as a way of chasing round locking threads but its utility is 
mitigated by the fact that the lock owner could transfer ownership 
immediately after the lock attempt. One possibility might be, say, to 
use the return value to order the failed thread in some sort of wait 
queue associated with the locked location, but it's not clear to me how 
you could make that work effectively.

n.b. Apologies for mixing Tim Harris's Java atomic syntax with C addressing.

regards,


Andrew Dinn
-----------




More information about the jboss-development mailing list