Should I avoid compareAndSet with value-based classes?

classic Classic list List threaded Threaded
101 messages Options
1234 ... 6
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Should I avoid compareAndSet with value-based classes?

Michael Hixson
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
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Gil Tene-2
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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Brian S O'Neill-3
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 <[hidden email]> 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
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Gil Tene-2

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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Henrik Johansson-8

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?


On Thu, 6 Jul 2017, 07:12 Gil Tene, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Gil Tene-2


Sent from my iPad

On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko
In reply to this post by Gil Tene-2

> On 6 Jul 2017, at 06:11, Gil Tene <[hidden email]> 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).

That would be a silly thing to do.

Unless you also forbid casting them to Object, including implicit downcasting due to generics. Java type system is not ready for that.


All it is saying, is that because of factory methods you can’t tell whether two Optional.empty() are the same instance or not, even in the same instance of a VM.

I don’t see why anyone would want to impose any other meaning, especially the varieties of “explosive” treatment you mentioned.


Alex

> - 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 <[hidden email]> 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 <[hidden email]> 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
>> [hidden email]
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko
In reply to this post by Gil Tene-2
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 <[hidden email]> wrote:



Sent from my iPad

On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Henrik Johansson-8

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, <[hidden email]> 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 <[hidden email]> wrote:



Sent from my iPad

On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Gil Tene-2
In reply to this post by Alex Otenko


Sent from my iPad

On Jul 6, 2017, at 12:38 AM, Alex Otenko <[hidden email]> 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

It also means that even when:

  LocalDateTime d = a;
  ...
  (a == d) may or may not be true. And may change whether it is true or not at any time,


Alex

On 6 Jul 2017, at 08:28, Gil Tene <[hidden email]> wrote:



Sent from my iPad

On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko

On 6 Jul 2017, at 08:47, Gil Tene <[hidden email]> wrote:



Sent from my iPad

On Jul 6, 2017, at 12:38 AM, Alex Otenko <[hidden email]> 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

It also means that even when:

  LocalDateTime d = a;
  ...
  (a == d) may or may not be true. And may change whether it is true or not at any time,

I meant an even stronger assertion:

assert (a==b) == (b==a) : "No Byzantine optimizations"
assert (a==d) == (a==d): “No Byzantine optimizations"

Alex




Alex

On 6 Jul 2017, at 08:28, Gil Tene <[hidden email]> wrote:



Sent from my iPad

On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Millies, Sebastian

just out of curiosity: I am familiar with the term “Byzantine failure”, but what is a “Byzantine optimization”?

n  Sebastian

 

From: Concurrency-interest [mailto:[hidden email]] On Behalf Of Alex Otenko
Sent: Thursday, July 06, 2017 10:17 AM
To: Gil Tene
Cc: [hidden email]
Subject: Re: [concurrency-interest] Should I avoid compareAndSet with value-based classes?

 

 

On 6 Jul 2017, at 08:47, Gil Tene <[hidden email]> wrote:

 



Sent from my iPad


On Jul 6, 2017, at 12:38 AM, Alex Otenko <[hidden email]> 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

 

It also means that even when:

 

  LocalDateTime d = a;

  ...

  (a == d) may or may not be true. And may change whether it is true or not at any time,

 

I meant an even stronger assertion:

 

assert (a==b) == (b==a) : "No Byzantine optimizations"

assert (a==d) == (a==d): “No Byzantine optimizations"

 

Alex

 



 

 

Alex

 

On 6 Jul 2017, at 08:28, Gil Tene <[hidden email]> wrote:

 



Sent from my iPad


On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

 

 


Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt, Dr. Stefan Sigg; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Andrew Haley
In reply to this post by Michael Hixson
On 06/07/17 04:59, Michael Hixson 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?

java.time.Instant stores times that are longer than a JVM word, so
they cannot be CAS'd in a lock-free way unless a factory guarantees
that instances which compare equal also have the property of
reference equality.  j.t.Instant factories in the Java library are
explicitly documented *not* to have this property, so that doesn't
help.

If you want to be able to CAS a reference to a j.t.Instant, you're
going to have to wrap accesses to it in a synchronized block.  This is
a direct consequence of the JVM's inability to CAS multi-word objects.

There are some things we know, however, despite the documentation of
"Value-based Classes".  For any reference r, r == r.  If r refers to a
value-based class, r.equals(r) will always return true.  I don't think
that anything which appears in that section can overrule these basic
properties.  Because of this, you can keep a pool of Instant
instances and intern them, and then, I believe, a reference CAS will
work.  But you'll need a synchronized factory to do that.

Obviously a CAS-able timestamp would be a nice thing to have, but
java.time.Instant is not the timestamp you're looking for.

--
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko
In reply to this post by Millies, Sebastian
:-) the one causing Byzantine failures!

Given how underspecified the things generally are, and that the target audience of such javadoc is not a JVM implementor, we shouldn’t read too much into the possible freedoms the vague wording seems to imply. It shouldn’t suddenly break the promises about identity equality for specific instances.

All it’s saying is that, like Integer.from(10) may or may not return the same instance. It may or may not work the same way throughout the JVM’s lifetime, allowing the implementors to choose suitable caching strategies, code optimizations, etc - therefore should not rely on comparing identities, and such; for example, synchronized(Integer.from(10)) does not guarantee neither lock freedom, nor deadlock freedom. It should not say that suddenly it is unsafe to compare identities (like Gil suggests JVM could start throwing exceptions). It should not say that suddenly we shouldn’t be able to CAS (like Gil says suddenly the reference to instance can sneakily be replaced with something else).


Alex


On 6 Jul 2017, at 10:12, Millies, Sebastian <[hidden email]> wrote:

just out of curiosity: I am familiar with the term “Byzantine failure”, but what is a “Byzantine optimization”?
n  Sebastian
 
From: Concurrency-interest [[hidden email]] On Behalf Of Alex Otenko
Sent: Thursday, July 06, 2017 10:17 AM
To: Gil Tene
Cc: [hidden email]
Subject: Re: [concurrency-interest] Should I avoid compareAndSet with value-based classes?
 
 
On 6 Jul 2017, at 08:47, Gil Tene <[hidden email]> wrote:
 


Sent from my iPad


On Jul 6, 2017, at 12:38 AM, Alex Otenko <[hidden email]> 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
 
It also means that even when:
 
  LocalDateTime d = a;
  ...
  (a == d) may or may not be true. And may change whether it is true or not at any time,
 
I meant an even stronger assertion:
 
assert (a==b) == (b==a) : "No Byzantine optimizations"
assert (a==d) == (a==d): “No Byzantine optimizations"
 
Alex
 


 
 
Alex
 
On 6 Jul 2017, at 08:28, Gil Tene <[hidden email]> wrote:
 


Sent from my iPad


On Jul 5, 2017, at 11:51 PM, Henrik Johansson <[hidden email]> 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, <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
 
 

Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt, Dr. Stefan Sigg; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko
In reply to this post by Andrew Haley

> On 6 Jul 2017, at 10:13, Andrew Haley <[hidden email]> wrote:
>
> On 06/07/17 04:59, Michael Hixson 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?
>
> java.time.Instant stores times that are longer than a JVM word, so
> they cannot be CAS'd in a lock-free way unless a factory guarantees
> that instances which compare equal also have the property of
> reference equality.  j.t.Instant factories in the Java library are
> explicitly documented *not* to have this property, so that doesn't
> help.

That’s not entirely clear.

Wouldn’t this loop work:

volatile j.t.Instant curr = ...

j.t.Instant next = …
j.t.Instant tmp = ...
do {
  tmp = curr;
  if (tmp.equal(next)) break;
} while(!curr.CAS(tmp, next));

// assume curr is equal to next


> If you want to be able to CAS a reference to a j.t.Instant, you're
> going to have to wrap accesses to it in a synchronized block.  This is
> a direct consequence of the JVM's inability to CAS multi-word objects.

This is confusing.

Surely this isn’t talking about CASing a reference? The contents of the object can’t be assumed to have any atomicity properties, whether it is j.t.Instant or not.


Alex


>
> There are some things we know, however, despite the documentation of
> "Value-based Classes".  For any reference r, r == r.  If r refers to a
> value-based class, r.equals(r) will always return true.  I don't think
> that anything which appears in that section can overrule these basic
> properties.  Because of this, you can keep a pool of Instant
> instances and intern them, and then, I believe, a reference CAS will
> work.  But you'll need a synchronized factory to do that.
>
> Obviously a CAS-able timestamp would be a nice thing to have, but
> java.time.Instant is not the timestamp you're looking for.
>
> --
> Andrew Haley
> Java Platform Lead Engineer
> Red Hat UK Ltd. <https://www.redhat.com>
> EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Andrew Haley
On 06/07/17 11:41, Alex Otenko wrote:

>
>> On 6 Jul 2017, at 10:13, Andrew Haley <[hidden email]> wrote:
>>
>> On 06/07/17 04:59, Michael Hixson 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?
>>
>> java.time.Instant stores times that are longer than a JVM word, so
>> they cannot be CAS'd in a lock-free way unless a factory guarantees
>> that instances which compare equal also have the property of
>> reference equality.  j.t.Instant factories in the Java library are
>> explicitly documented *not* to have this property, so that doesn't
>> help.
>
> That’s not entirely clear.
>
> Wouldn’t this loop work:
>
> volatile j.t.Instant curr = ...
>
> j.t.Instant next = …
> j.t.Instant tmp = ...
> do {
>   tmp = curr;
>   if (tmp.equal(next)) break;
> } while(!curr.CAS(tmp, next));
>
> // assume curr is equal to next

Something like that, yes.  But it's going to be evil if there are
several high-frequency writers.  If you're doing all that work in
order to CAS a timestamp, why not use a synchronized block?  It would
at least be less prone to the thundering herd, and we'd generate
pretty decent code for that.  It'd be interesting to compare and
contrast the two approaches for contended and non-contended cases.

>> If you want to be able to CAS a reference to a j.t.Instant, you're
>> going to have to wrap accesses to it in a synchronized block.  This is
>> a direct consequence of the JVM's inability to CAS multi-word objects.
>
> This is confusing.
>
> Surely this isn’t talking about CASing a reference? The contents of
> the object can’t be assumed to have any atomicity properties,
> whether it is j.t.Instant or not.

I agree.  I'm trying to look at what the OP actually wants to do: I
assume this is some kind of atomic timestamp, and the OP wants to be
able to CAS an instance of j.u.Instant.

--
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Alex Otenko
Thanks, Andrew. That clarifies.

Yes, CAS loop example is just for the sake of argument.

Alex

On 6 Jul 2017, at 12:20, Andrew Haley <[hidden email]> wrote:

On 06/07/17 11:41, Alex Otenko wrote:

On 6 Jul 2017, at 10:13, Andrew Haley <[hidden email]> wrote:

On 06/07/17 04:59, Michael Hixson 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?

java.time.Instant stores times that are longer than a JVM word, so
they cannot be CAS'd in a lock-free way unless a factory guarantees
that instances which compare equal also have the property of
reference equality.  j.t.Instant factories in the Java library are
explicitly documented *not* to have this property, so that doesn't
help.

That’s not entirely clear.

Wouldn’t this loop work:

volatile j.t.Instant curr = ...

j.t.Instant next = …
j.t.Instant tmp = ...
do {
 tmp = curr;
 if (tmp.equal(next)) break;
} while(!curr.CAS(tmp, next));

// assume curr is equal to next

Something like that, yes.  But it's going to be evil if there are
several high-frequency writers.  If you're doing all that work in
order to CAS a timestamp, why not use a synchronized block?  It would
at least be less prone to the thundering herd, and we'd generate
pretty decent code for that.  It'd be interesting to compare and
contrast the two approaches for contended and non-contended cases.

If you want to be able to CAS a reference to a j.t.Instant, you're
going to have to wrap accesses to it in a synchronized block.  This is
a direct consequence of the JVM's inability to CAS multi-word objects.

This is confusing.

Surely this isn’t talking about CASing a reference? The contents of
the object can’t be assumed to have any atomicity properties,
whether it is j.t.Instant or not.

I agree.  I'm trying to look at what the OP actually wants to do: I
assume this is some kind of atomic timestamp, and the OP wants to be
able to CAS an instance of j.u.Instant.

-- 
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Doug Lea
In reply to this post by Andrew Haley
On 07/06/2017 05:13 AM, Andrew Haley wrote:

> On 06/07/17 04:59, Michael Hixson 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?
>
> java.time.Instant stores times that are longer than a JVM word, so
> they cannot be CAS'd in a lock-free way unless a factory guarantees
> that instances which compare equal also have the property of
> reference equality.  j.t.Instant factories in the Java library are
> explicitly documented *not* to have this property, so that doesn't
> help.
>
> If you want to be able to CAS a reference to a j.t.Instant, you're
> going to have to wrap accesses to it in a synchronized block.  This is
> a direct consequence of the JVM's inability to CAS multi-word objects.

Right. Hoping not add confusion, the underlying issues also arise in
upcoming Value Types. (https://wiki.openjdk.java.net/display/valhalla/Main)

These "actual" value types will (like primitives) use "==" for
(possibly multiple component) equality.
VarHandles for atomic operations will need to use some form of locking.
Possibilities (not yet fully implemented) include some combination of
(1) just using a global lock for all values (2) using a pool of locks
(e.g., hashed on containing object identityHashCode), and/or
(3) using native hardware transactions on platforms supporting them
(e.g., recent x86). Plus potential specializations for non-SC VarHandle
operations (e.g.,  seqlocks for getAcquire).

In principle, you could apply most of these (no HTM) for current uses of
value-based classes.

-Doug





>
> There are some things we know, however, despite the documentation of
> "Value-based Classes".  For any reference r, r == r.  If r refers to a
> value-based class, r.equals(r) will always return true.  I don't think
> that anything which appears in that section can overrule these basic
> properties.  Because of this, you can keep a pool of Instant
> instances and intern them, and then, I believe, a reference CAS will
> work.  But you'll need a synchronized factory to do that.
>
> Obviously a CAS-able timestamp would be a nice thing to have, but
> java.time.Instant is not the timestamp you're looking for.
>

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Fwd: Should I avoid compareAndSet with value-based classes?

Michael Hixson
In reply to this post by Andrew Haley
Forwarding this reply of mine because I forgot to CC the mailing list.


---------- Forwarded message ----------
From: Michael Hixson <[hidden email]>
Date: Thu, Jul 6, 2017 at 7:24 AM
Subject: Re: [concurrency-interest] Should I avoid compareAndSet with
value-based classes?
To: Andrew Haley <[hidden email]>


On Thu, Jul 6, 2017 at 4:20 AM, Andrew Haley <[hidden email]> wrote:

> On 06/07/17 11:41, Alex Otenko wrote:
>>
>>> On 6 Jul 2017, at 10:13, Andrew Haley <[hidden email]> wrote:
>>>
>>> On 06/07/17 04:59, Michael Hixson 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?
>>>
>>> java.time.Instant stores times that are longer than a JVM word, so
>>> they cannot be CAS'd in a lock-free way unless a factory guarantees
>>> that instances which compare equal also have the property of
>>> reference equality.  j.t.Instant factories in the Java library are
>>> explicitly documented *not* to have this property, so that doesn't
>>> help.
>>
>> That’s not entirely clear.
>>
>> Wouldn’t this loop work:
>>
>> volatile j.t.Instant curr = ...
>>
>> j.t.Instant next = …
>> j.t.Instant tmp = ...
>> do {
>>   tmp = curr;
>>   if (tmp.equal(next)) break;
>> } while(!curr.CAS(tmp, next));
>>
>> // assume curr is equal to next
>
> Something like that, yes.  But it's going to be evil if there are
> several high-frequency writers.  If you're doing all that work in
> order to CAS a timestamp, why not use a synchronized block?  It would
> at least be less prone to the thundering herd, and we'd generate
> pretty decent code for that.  It'd be interesting to compare and
> contrast the two approaches for contended and non-contended cases.

The main reason I reached for AtomicReference is that I thought, "I
want thread-safe updates to this read-heavy value where writes won't
get lost if there's contention -- this sounds like the sort of problem
that java.util.concurrent.atomic solves."

As a minor point, I wanted synchronization on reads to be as
minor/invisible as possible, to affect the readers' behavior as little
as possible (in comparison to their behavior when the value they're
reading a constant value with no synchronization).

But if AtomicReference is simply the wrong tool to use here, I
shouldn't use it.  That's fine.

>
>>> If you want to be able to CAS a reference to a j.t.Instant, you're
>>> going to have to wrap accesses to it in a synchronized block.  This is
>>> a direct consequence of the JVM's inability to CAS multi-word objects.
>>
>> This is confusing.
>>
>> Surely this isn’t talking about CASing a reference? The contents of
>> the object can’t be assumed to have any atomicity properties,
>> whether it is j.t.Instant or not.
>
> I agree.  I'm trying to look at what the OP actually wants to do: I
> assume this is some kind of atomic timestamp, and the OP wants to be
> able to CAS an instance of j.u.Instant.

It was more of a general worry and question.  Should I ever use
AtomicReference with value-based classes?  It sounds like the answer
is no.

But here's some code that illustrates the specific problem I was
trying to solve.  I think it "works" right now, but that it's in
violation of the spec for value-based classes and so possibly not
future-proof, and I think I understand how to fix it now.  Thanks for
the tips.

    class MutableClock {

        static MutableClock create(Instant instant, ZoneId zone) {
            return new MutableClock(
                    new AtomicReference<>(instant),
                    zone);
        }

        private final AtomicReference<Instant> instantHolder;
        private final ZoneId zone;

        private MutableClock(
                AtomicReference<Instant> instantHolder,
                ZoneId zone) {
            this.instantHolder = instantHolder;
            this.zone = zone;
        }

        Instant instant() {
            return instantHolder.get();
        }

        ZoneId getZone() {
            return zone;
        }

        void setInstant(Instant newInstant) {
            instantHolder.set(newInstant);
        }

        void add(Duration amountToAdd) {
            // this is the part that uses == and CAS
            instantHolder.updateAndGet(
                  instant -> instant.plus(amountToAdd));
        }

        MutableClock withZone(ZoneId newZone) {
            // conveniently, AtomicReference also acts as a
            // vehicle for "shared updates" between instances
            // of my class
            return new MutableClock(instantHolder, newZone);
        }
    }

-Michael
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Should I avoid compareAndSet with value-based classes?

Michael Hixson
In reply to this post by Andrew Haley
On Thu, Jul 6, 2017 at 7:27 AM, Andrew Haley <[hidden email]> wrote:

> On 06/07/17 15:00, Michael Hixson wrote:
>> Am I understanding you correctly that the reason compareAndSet does
>> the wrong/unwanted thing here is not actually because of the ==
>> comparison and ties to object identity, but because the value can't be
>> written atomically?
>
> I was trying to clarify, but my explanation seems to have made things worse.
>
> No, I'm not saying that.  The value can't be written atomically, that
> is true.  I am saying that it would be nice if we could CAS the
> *value* of a java.time.Instant, but we can't.  All we can CAS is a
> reference to an Instant, but we're not supposed to do that because
> we're not supposed to compare value-based classes with reference
> equality.  So, it's best to use a synchronized block.
>
> --
> Andrew Haley
> Java Platform Lead Engineer
> Red Hat UK Ltd. <https://www.redhat.com>
> EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671

(re CC'ing the mailing list, oops)

Ah ok.  That makes sense, thanks.

-Michael
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
1234 ... 6
Loading...