[concurrency-interest] Should I avoid compareAndSet with value-based classes?

Henrik Johansson dahankzter at gmail.com
Thu Jul 6 03:43:39 EDT 2017


I was kind of hoping, perhaps naively, that the value based classes would
be treated as the primitive types.

On Thu, 6 Jul 2017, 09:38 Alex Otenko, <oleksandr.otenko at gmail.com> wrote:

> All it is saying is:
>
>   LocalDateTime a = LocalDateTime.parse("2007-12-03T10:15:30");
>   LocalDateTime b = LocalDateTime.parse("2007-12-03T10:15:30");
>   LocalDateTime c = LocalDateTime.parse("2007-12-03T10:15:30");
>
> a==b && b==c can be true and can be false
>
> Alex
>
> On 6 Jul 2017, at 08:28, Gil Tene <gil at azul.com> wrote:
>
>
>
> Sent from my iPad
>
> On Jul 5, 2017, at 11:51 PM, Henrik Johansson <dahankzter at gmail.com>
> wrote:
>
> Oh, without having followed the value type discussions I think it was a
> mistake to not "fix" equality. Why not make it a deep comparison if the
> reference is different? If it points to the same object we are done
> otherwise start checking the struct content.
>
> There may be a lot I missed here but a new type of object could be allowed
> to have different meaning equality. Right?
>
> .equals() means what you want it to mean. == and != (and the compare in
> compareAndSet) mean very specific things, and cannot be overridden.
>
> For non-reference value types (int, long, char, etc.), == and != are value
> comparisons. An int has no identity. Just a value:
>   int a = 5;
>   int b = 5;
>   boolean y = (a == b);  // true
>
> For references to instances of (non value-based) classes, == and != can be
> thought of as comparing the value of the reference (and not the contents of
> the object instances). This is an identity comparison, which ignores values
> within the object:
>   Integer a = new Integer(5);
>   Integer b = new Integer(5);
>   boolean x = a.equals(b);   // true
>   boolean y = (a == b);   // false
>
> And for references to value-based classes (which is a relatively new
> thing, but is part of Java 8), the meaning of == and != appears to be
> undefined. E.g.:
>
>   LocalDateTime a = LocalDateTime.parse("2007-12-03T10:15:30");
>   LocalDateTime b = LocalDateTime.parse("2007-12-03T10:15:30");
>   boolean x = a.equals(b);   // true
>   boolean y = (a == b);   // unpredictable, undefined, who knows.
>                                          // Could be true, could be false.
>                                          // Could theoretically change
> the values of a or b, or of something else
>
>
>
> On Thu, 6 Jul 2017, 07:12 Gil Tene, <gil at azul.com> wrote:
>
>>
>> I'd take that documentation seriously. It basically says that ==, !=,
>> synchronization, identity hashing, and serialization are undefined
>> behaviors.
>>
>> While the *current* implementations may carry some semi-intuitive
>> behvaiors, e.g. where == indicates true when comparing two references to
>> instances of a value-based class where the value of the references is the
>> same, there is no guarantee that at some point in the [near or far] future
>> that behavior will remain. Specifically, attempting == (or !=, or
>> synchronization, etc., including compareAndSet) on a reference to a value
>> based class is allowed to do ANYTHING in the future.
>> For example:
>> - It may throw an exception (something it should probably start doing
>> ASAP to avoid future surprises).
>> - It may return always-false, even when the two references are "to the
>> same instance" (and probably will, through many possible value-based
>> compiler optimizations that will erase the unneeded notion of reference and
>> identity).
>> - It may overwrite random locations in memory or to variables that the
>> code performing the operation has the privilege to write to (which it
>> probably shouldn't, but that's certainly included in what "undefined" and
>> "unpredictable effects" can mean).
>> - It may sometimes do one of the above, and sometimes seem to be doing
>> what you mean it to do. Switching between modes on a whim (e.g. when a tier
>> 2 optimizing compilation is applied, or when the mutton is nice and lean
>> and the tomato is ripe).
>>
>> So no, there is no way for compareAndSet to work "correctly" on a
>> reference to an instance of a value-based class. Even if it happens to
>> appear to work "correctly" now, expect it to blow up in bad and potentially
>> silent ways in the future.
>>
>> — Gil.
>>
>> > On Jul 5, 2017, at 9:47 PM, Brian S O'Neill <bronee at gmail.com> wrote:
>> >
>> > I think the wording in the value-based document is too strong. It's
>> perfectly fine to compare value based instances using ==, but it can lead
>> to confusing results when comparing distinct instances with equivalent
>> state. Using compareAndSet with a box isn't necessary for it to work
>> "correctly" with a value-based class.
>> >
>> > By "correctly", I mean the compareAndSet operation works correctly,
>> using == comparison. However, if your intention is for compareAndSet to
>> compare Instants based on their state, then this of course won't work
>> properly.
>> >
>> > If you want to perform a compareAndSet for an Instant's state (time
>> since epoch), then you need to use something that can be compared
>> atomically. This means the state must be representable in a 64-bit value or
>> smaller. The Instant class measures time using a 64-bit long and a 32-bit
>> int, and so this state cannot be compared atomically. You'd have to chop
>> off some precision or use something else.
>> >
>> >
>> > On 2017-07-05 09:20 PM, Gil Tene wrote:
>> >> Reference equality for value based classes (as referenced below) lacks
>> meaning, as there is no notion of identity in such classes (only a notion
>> of value). And since compareAndSet on reference fields is basically an
>> idenitity-based operation [in the compare part], the two won't mix well
>> logically.
>> >> Specifically, while two references to e.g. java.time.LocalDateTime
>> instances being == to each other *probably* means that the two are actually
>> equal in value, the opposite is not true: Being != to each other does NOT
>> mean that they are logically different. As such, the "compare" part in
>> compareAndSet may falsely fail even when the two instances are logically
>> equal to each other, leaving the rest of your logic potentially exposed.
>> >> Bottom line: given the explicit warning to not use == and != on
>> references to value-based instances, I'd avoid using compareAndSet on those
>> references. If you really need to use a value-based class in your logic,
>> consider boxing it in another object that has [normal] identity.
>> >> — Gil.
>> >>> On Jul 5, 2017, at 8:59 PM, Michael Hixson <michael.hixson at gmail.com>
>> wrote:
>> >>>
>> >>> AtomicReference and VarHandle are specified to use == in compareAndSet
>> >>> (and related) operations [1].  Using == to compare instances of
>> >>> value-based classes may lead to "unpredictable results" [2].  Does
>> >>> this mean I should avoid using compareAndSet with arguments that are
>> >>> instances of value-based classes?
>> >>>
>> >>> It seems like the documentation clearly tells me "yes, avoid doing
>> >>> that" but I'm hoping I misunderstood, or maybe AtomicReference and
>> >>> VarHandle are exempt somehow.  Otherwise, how do I implement
>> >>> non-broken compareAndSet and updateAndGet for a java.time.Instant
>> >>> value for example?  Do I have to box the value in something that's not
>> >>> a value-based class first, like AtomicReference<Box<Instant>>?
>> >>>
>> >>> -Michael
>> >>>
>> >>> [1]
>> http://download.java.net/java/jdk9/docs/api/java/util/concurrent/atomic/AtomicReference.html#compareAndSet-V-V-
>> >>> [2]
>> http://download.java.net/java/jdk9/docs/api/java/lang/doc-files/ValueBased.html
>> >
>> > _______________________________________________
>> > Concurrency-interest mailing list
>> > Concurrency-interest at cs.oswego.edu
>> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20170706/7e813365/attachment-0001.html>


More information about the Concurrency-interest mailing list