46

(note that this question is not about CAS, it's about the "May fail spuriously" Javadoc).

The only difference in the Javadoc between these two methods from the AtomicInteger class is that the weakCompareAndSet contains the comment: "May fail spuriously".

Now unless my eyes are cheated by some spell, both method do look to be doing exactly the same:

public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

/* ...
 * May fail spuriously.
 */
public final boolean weakCompareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

So I realize that "May" doesn't mean "Must" but then why don't we all start adding this to our codebase:

public void doIt() {
    a();
}

/**
 * May fail spuriously
 */
public void weakDoIt() {
    a();
}

I'm really confused with that weakCompareAndSet() that appears to do the same as the compareAndSet() yet that "may fail spuriously" while the other can't.

Apparently the "weak" and the "spurious fail" are in a way related to "happens-before" ordering but I'm still very confused by these two AtomicInteger (and AtomicLong etc.) methods: because apparently they call exactly the same unsafe.compareAndSwapInt method.

I'm particularly confused in that AtomicInteger got introduced in Java 1.5, so after the Java Memory Model change (so it is obviously not something that could "fail spuriously in 1.4" but whose behavior changed to "shall not fail spuriously in 1.5").

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
SyntaxT3rr0r
  • 27,745
  • 21
  • 87
  • 120
  • Weird indeed. It could be API future proofing, but this is an odd way to go about it. It seems that all of the `AtomicXYZ` classes do the same thing in `compareAndSet` and `weakCompareAndSet`, so it's not as if it's for consistency between implementations, either. – skaffman Mar 14 '10 at 18:43
  • See also http://stackoverflow.com/questions/4183202/java-compare-and-swap-semantics-and-performance – assylias May 13 '13 at 21:56
  • http://stackoverflow.com/questions/355365/what-does-spurious-failure-on-atomicinteger-weakcompareandset-mean – Ciro Santilli OurBigBook.com Jun 16 '15 at 14:03
  • Mostly I'm upvoting because it's a good question... but a little part of me is upvoting for the LotR reference. :-) – Ti Strga Jan 22 '18 at 17:40

2 Answers2

21

There is a difference between implementation and specification...

Whilst on a particular implementation there may not be much point in providing different implementations, future implementations perhaps on different hardware may want to. Whether this method carries its weight in the API is debatable.

Also the weak methods do not have happens-before ordering defined. The non-weak versions behave like volatile fields.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • @Tom Hawtin - tackline: +1... Do you know of any JVM implementation (Sun or non-Sun) on any hardware where there are different implementation for such methods? – SyntaxT3rr0r Mar 14 '10 at 18:55
  • No. I don't even know if there is any mainstream hardware where it would make a difference. I believe in order to get the weak volatile behaviour, you have to do it for everything. Of course, the other side of things is the compiler, which could leave data in registers which would otherwise be flushed. – Tom Hawtin - tackline Mar 14 '10 at 19:21
  • "Also the weak methods do not have happens-before ordering defined. The non-weak versions behave like volatile fields." If so, What's the point of such a method in the java.util.concurrent.atomic; package? – Rollerball Jun 03 '13 at 16:40
  • @Rollerball They still support atomic operations that would otherwise be composite. – Tom Hawtin - tackline Jun 03 '13 at 18:07
1

Just to play a bit, if your question were

How can weakDoIt fail spuriously if it is implemented exactly like doIt?

here is the answer!

public void doIt() {
    a();
}

/**
 * May fail spuriously
 */
public void weakDoIt() {
    a();
}

void a(){
    if(Thread.currentThread().getStackTrace()[2].toString().contains("weakDoIt"))
        System.out.println("I will fail spuriously!");
    else System.out.println("I won't fail spuriously!");
}
Luigi Cortese
  • 10,841
  • 6
  • 37
  • 48