VolatileArray

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

VolatileArray

JSR166 Concurrency mailing list
Hi,

We know that in Java, reads from and writes to array slots are not
volatile. We can use AtomicXXXArray to get volatile access but for the
price of a wrapper dereference. Suppose that one does not need total
ordering when publishing elements via array slots and just wants to be
sure that on the reading side, the reads from array slots are not
hoisted out of loops so that they do not appear to return stale values
for indefinite amount of time.

Would something like that help?

public class VolatileArray {

     private volatile Object[] array;

     public VolatileArray(int length) {
         array = new Object[length];
     }

     public Object get(int i) {
         Object[] a;
         do {
             a = array; // read reference to array
         } while (a == null);
         return a[i];   // read array slot
     }

     public void set(int i, Object o) {
         Object[] a;
         do { a = array; } while (a == null);
         a[i] = o;  // write array slot
         array = a; // write reference to array
     }
}

Note that this is not a utility class to be used in code
(AtomicReferenceArray could be used instead). It just represents an idea
of how to publish references (via data race of course) but still ensure
that the reading side will see published references, using only basic
Java (no VarHandle(s) or Unsafe).

Does JMM guarantee this to work or not?

Regards, Peter

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

Re: VolatileArray

JSR166 Concurrency mailing list
Hi Peter,

I'm not a JMM expert but that pattern looks fragile to me. 

If you are on Java 9 or later, you can use `setRelease` [1] on the  AtomicReferenceArray and simply use plain `set` for the last element to flush all before. Note that Java 9 allows you to manipulate plain arrays via VarHandles so there might be no need for AtomicReferenceArray indirection after all.

If you are on Java 6-8, you can still use `lazySet` [2] for the same purpose and `set` for the last element.





Peter Levart via Concurrency-interest <[hidden email]> ezt írta (időpont: 2018. ápr. 4., Sze, 10:59):
Hi,

We know that in Java, reads from and writes to array slots are not
volatile. We can use AtomicXXXArray to get volatile access but for the
price of a wrapper dereference. Suppose that one does not need total
ordering when publishing elements via array slots and just wants to be
sure that on the reading side, the reads from array slots are not
hoisted out of loops so that they do not appear to return stale values
for indefinite amount of time.

Would something like that help?

public class VolatileArray {

     private volatile Object[] array;

     public VolatileArray(int length) {
         array = new Object[length];
     }

     public Object get(int i) {
         Object[] a;
         do {
             a = array; // read reference to array
         } while (a == null);
         return a[i];   // read array slot
     }

     public void set(int i, Object o) {
         Object[] a;
         do { a = array; } while (a == null);
         a[i] = o;  // write array slot
         array = a; // write reference to array
     }
}

Note that this is not a utility class to be used in code
(AtomicReferenceArray could be used instead). It just represents an idea
of how to publish references (via data race of course) but still ensure
that the reading side will see published references, using only basic
Java (no VarHandle(s) or Unsafe).

Does JMM guarantee this to work or not?

Regards, Peter

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


--
Best regards,
David Karnok

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

Re: VolatileArray

JSR166 Concurrency mailing list
Hi David,

On 04/04/2018 11:17 AM, Dávid Karnok wrote:
Hi Peter,

I'm not a JMM expert but that pattern looks fragile to me. 

If you are on Java 9 or later, you can use `setRelease` [1] on the  AtomicReferenceArray and simply use plain `set` for the last element to flush all before. Note that Java 9 allows you to manipulate plain arrays via VarHandles so there might be no need for AtomicReferenceArray indirection after all.

If you are on Java 6-8, you can still use `lazySet` [2] for the same purpose and `set` for the last element.

Yes, I know, but I specifically don't want (or can't) use any of these utilities. Let's assume that I want to use an array to publish (and it's ok to publish via data race) references to objects that contain just final fields. I just want to ensure that published objects are seen by readers that are accessing them in a loop. I want to prevent hoisting these reads out of loop. Specifically I want to (eventually) see new reference of some object published in the same array slot as some other old object. The state transitions in individual slots are not only null -> nonnull, but also nonnull -> nonnull and nonnull -> null. So I'm not implementing a compute-once-and-keep-forever cache. The contents of array changes.

Regards, Peter


Peter Levart via Concurrency-interest <[hidden email]> ezt írta (időpont: 2018. ápr. 4., Sze, 10:59):
Hi,

We know that in Java, reads from and writes to array slots are not
volatile. We can use AtomicXXXArray to get volatile access but for the
price of a wrapper dereference. Suppose that one does not need total
ordering when publishing elements via array slots and just wants to be
sure that on the reading side, the reads from array slots are not
hoisted out of loops so that they do not appear to return stale values
for indefinite amount of time.

Would something like that help?

public class VolatileArray {

     private volatile Object[] array;

     public VolatileArray(int length) {
         array = new Object[length];
     }

     public Object get(int i) {
         Object[] a;
         do {
             a = array; // read reference to array
         } while (a == null);
         return a[i];   // read array slot
     }

     public void set(int i, Object o) {
         Object[] a;
         do { a = array; } while (a == null);
         a[i] = o;  // write array slot
         array = a; // write reference to array
     }
}

Note that this is not a utility class to be used in code
(AtomicReferenceArray could be used instead). It just represents an idea
of how to publish references (via data race of course) but still ensure
that the reading side will see published references, using only basic
Java (no VarHandle(s) or Unsafe).

Does JMM guarantee this to work or not?

Regards, Peter

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


--
Best regards,
David Karnok


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

Re: VolatileArray

JSR166 Concurrency mailing list
In reply to this post by JSR166 Concurrency mailing list
On 04/04/2018 10:58 AM, Peter Levart via Concurrency-interest wrote:

> We know that in Java, reads from and writes to array slots are not volatile. We can use
> AtomicXXXArray to get volatile access but for the price of a wrapper dereference. Suppose that one
> does not need total ordering when publishing elements via array slots and just wants to be sure that
> on the reading side, the reads from array slots are not hoisted out of loops so that they do not
> appear to return stale values for indefinite amount of time.
>
> Would something like that help?
>
> public class VolatileArray {
>
>     private volatile Object[] array;
>
>     public VolatileArray(int length) {
>         array = new Object[length];
>     }
>
>     public Object get(int i) {
>         Object[] a;
>         do {
>             a = array; // read reference to array
>         } while (a == null);
>         return a[i];   // read array slot
>     }
>
>     public void set(int i, Object o) {
>         Object[] a;
>         do { a = array; } while (a == null);
>         a[i] = o;  // write array slot
>         array = a; // write reference to array
>     }
> }
>
> Note that this is not a utility class to be used in code (AtomicReferenceArray could be used
> instead). It just represents an idea of how to publish references (via data race of course) but
> still ensure that the reading side will see published references, using only basic Java (no
> VarHandle(s) or Unsafe).
>
> Does JMM guarantee this to work or not?

I don't think it does.

Trivial and intuitive failure mode is "premature publication": In set(), writes to "o" happen
unordered to the store to a[i] -- volatile-acquire for $array not preventing much of that -- which
means the object could be available in a[i] in incomplete state, and get() reads that incomplete
state. It is too late to deal with that race in get() at that point.

In other words, you want the releasing store *to* a[i], and acquiring *from* a[i] -- that is, given
a[i] is exposed already, you need to order operations relative to a[i] load/stores themselves. That
is what VarHandles and AtomicXXXArray do.

In yet another words, given that a[i] is exposed already, you are facing seeing the racy update of
a[i] *after* you have stored/loaded the $array itself:

 Thread 1:                                  Thread 2:

 // --------------- Good case ------------------------------------------------------
   a[i] = o1;
   o1.x = 42; // unordered store
   array = a; // (*)
                                              a = array;
                                              o = a[i];
                                              assert (o.x == 42); // passes

 // --------------- Bad case ------------------------------------------------------

   a[i] = o2;
                                              a = array; // (**)
                                              o = a[i];
                                              assert (o.x == 43); // fails!
   o2.x = 43; // unordered store
   array = a;

Oops. The problem is, you might think that at (*) you are reading the store at (**), and that
provides you ordering guarantees, while in reality that gives you nothing in bad case, because the
racy update is happening nevertheless.

The way out without VarHandles or AtomicXXXArray-s is to "version" the array, increment the version
before and after updating the a[i], and and check if version had changed while we were reading the
a[i] in another thread, but that reinvents sequence locks. Which might be the answer for you:
optimistic StampedLock in get(), maybe?

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

Re: VolatileArray

JSR166 Concurrency mailing list
Hi Aleksey,

On 04/04/2018 12:20 PM, Aleksey Shipilev wrote:

> On 04/04/2018 10:58 AM, Peter Levart via Concurrency-interest wrote:
>> We know that in Java, reads from and writes to array slots are not volatile. We can use
>> AtomicXXXArray to get volatile access but for the price of a wrapper dereference. Suppose that one
>> does not need total ordering when publishing elements via array slots and just wants to be sure that
>> on the reading side, the reads from array slots are not hoisted out of loops so that they do not
>> appear to return stale values for indefinite amount of time.
>>
>> Would something like that help?
>>
>> public class VolatileArray {
>>
>>      private volatile Object[] array;
>>
>>      public VolatileArray(int length) {
>>          array = new Object[length];
>>      }
>>
>>      public Object get(int i) {
>>          Object[] a;
>>          do {
>>              a = array; // read reference to array
>>          } while (a == null);
>>          return a[i];   // read array slot
>>      }
>>
>>      public void set(int i, Object o) {
>>          Object[] a;
>>          do { a = array; } while (a == null);
>>          a[i] = o;  // write array slot
>>          array = a; // write reference to array
>>      }
>> }
>>
>> Note that this is not a utility class to be used in code (AtomicReferenceArray could be used
>> instead). It just represents an idea of how to publish references (via data race of course) but
>> still ensure that the reading side will see published references, using only basic Java (no
>> VarHandle(s) or Unsafe).
>>
>> Does JMM guarantee this to work or not?
> I don't think it does.
>
> Trivial and intuitive failure mode is "premature publication": In set(), writes to "o" happen
> unordered to the store to a[i] -- volatile-acquire for $array not preventing much of that -- which
> means the object could be available in a[i] in incomplete state, and get() reads that incomplete
> state. It is too late to deal with that race in get() at that point.
>
> In other words, you want the releasing store *to* a[i], and acquiring *from* a[i] -- that is, given
> a[i] is exposed already, you need to order operations relative to a[i] load/stores themselves. That
> is what VarHandles and AtomicXXXArray do.

Or I can achieve that ordering (of reads and writes beyond o) by
ensuring o is always an immutable object with final fields. Perhaps I
would have better demonstrated the idea using an array of primitives
instead of references...

>
> In yet another words, given that a[i] is exposed already, you are facing seeing the racy update of
> a[i] *after* you have stored/loaded the $array itself:
>
>   Thread 1:                                  Thread 2:
>
>   // --------------- Good case ------------------------------------------------------
>     a[i] = o1;
>     o1.x = 42; // unordered store
>     array = a; // (*)
>                                                a = array;
>                                                o = a[i];
>                                                assert (o.x == 42); // passes
>
>   // --------------- Bad case ------------------------------------------------------
>
>     a[i] = o2;
>                                                a = array; // (**)
>                                                o = a[i];
>                                                assert (o.x == 43); // fails!
>     o2.x = 43; // unordered store
>     array = a;
>
> Oops. The problem is, you might think that at (*) you are reading the store at (**), and that
> provides you ordering guarantees, while in reality that gives you nothing in bad case, because the
> racy update is happening nevertheless.
>
> The way out without VarHandles or AtomicXXXArray-s is to "version" the array, increment the version
> before and after updating the a[i], and and check if version had changed while we were reading the
> a[i] in another thread, but that reinvents sequence locks. Which might be the answer for you:
> optimistic StampedLock in get(), maybe?

I think that using anything more would defeat the purpose of not using
any utilities (suppose I want to do something in low-level JDK which is
used by those utilities an I want to prevent bootstrapping issues).

But I think that my example might be flawed nevertheless. I wanted to
prevent hoisting of array reads out of loops, but then I realized that
the following hypothetical optimization of some JIT might defeat that
and may still satisfy JMM (for the purpose of this example,
cached[A,O,I] are locals hoisted out of loop that calls into get(i) and
doesn't call into set(i, o)):

     Object[] cachedA = null;
     Object cachedO = new Object();
     int cachedI = 0;

...

     public Object get(int i) {
         Object[] a;
         do {
             a = array; // read reference to array
         } while (a == null);

         if (a == cachedA && i == cachedI) {
             return cachedO;
         } else {
             cachedA = a;
             cachedI = i;
             return cachedO = a[i];   // read array slot
         }
     }

Is such transformation legal according to JMM? Could we argue that
reading thread did not observe the volatile write of array if that array
stayed the same and therefore is not obligated to order other accesses
around such volatile read of array?

Regards,
Peter

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

Re: VolatileArray

JSR166 Concurrency mailing list
Ops,

On 04/04/2018 01:04 PM, Peter Levart wrote:
> Object[] cachedA = null;
>     Object cachedO = new Object();
>     int cachedI = 0;

I wanted to write something like this to pre-initialize the locals (i.e.
something that will never match in get(i) the 1st time around):

     Object[] cachedA = new Object[0];
     Object cachedO = null;
     int cachedI = 0;

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

Re: VolatileArray

JSR166 Concurrency mailing list
In reply to this post by JSR166 Concurrency mailing list
It’s hard to see what you have in mind. In simple terms a non-volatile load always has to be issued after volatile loads, so the code won’t behave like it’s “caching”.

In JMM terms the non-volatile load observes at least the value stored before the volatile store preceding the volatile load in synchronization order. (But is allowed to observe any other non-volatile stores that appear after the volatile store in program order)

So if you imagine one thread producing:

a[i] = o1; // non-volatile store
array = a; // volatile store
a[i] = o2;
array = a;

and the other thread producing

a = array;
o1 = a[i];
a = array;
o2 = a[i];

the second thread cannot behave as if it saw a non-null value o1, and kept looping. On the other hand, if this thread observes o1 is null, the JVM has to place the corresponding a=array in the synchronization order before any volatile store array=a that follows a store of a non-null value to a[i].

Alex


On 4 Apr 2018, at 12:04, Peter Levart via Concurrency-interest <[hidden email]> wrote:

Hi Aleksey,

On 04/04/2018 12:20 PM, Aleksey Shipilev wrote:
On 04/04/2018 10:58 AM, Peter Levart via Concurrency-interest wrote:
We know that in Java, reads from and writes to array slots are not volatile. We can use
AtomicXXXArray to get volatile access but for the price of a wrapper dereference. Suppose that one
does not need total ordering when publishing elements via array slots and just wants to be sure that
on the reading side, the reads from array slots are not hoisted out of loops so that they do not
appear to return stale values for indefinite amount of time.

Would something like that help?

public class VolatileArray {

    private volatile Object[] array;

    public VolatileArray(int length) {
        array = new Object[length];
    }

    public Object get(int i) {
        Object[] a;
        do {
            a = array; // read reference to array
        } while (a == null);
        return a[i];   // read array slot
    }

    public void set(int i, Object o) {
        Object[] a;
        do { a = array; } while (a == null);
        a[i] = o;  // write array slot
        array = a; // write reference to array
    }
}

Note that this is not a utility class to be used in code (AtomicReferenceArray could be used
instead). It just represents an idea of how to publish references (via data race of course) but
still ensure that the reading side will see published references, using only basic Java (no
VarHandle(s) or Unsafe).

Does JMM guarantee this to work or not?
I don't think it does.

Trivial and intuitive failure mode is "premature publication": In set(), writes to "o" happen
unordered to the store to a[i] -- volatile-acquire for $array not preventing much of that -- which
means the object could be available in a[i] in incomplete state, and get() reads that incomplete
state. It is too late to deal with that race in get() at that point.

In other words, you want the releasing store *to* a[i], and acquiring *from* a[i] -- that is, given
a[i] is exposed already, you need to order operations relative to a[i] load/stores themselves. That
is what VarHandles and AtomicXXXArray do.

Or I can achieve that ordering (of reads and writes beyond o) by ensuring o is always an immutable object with final fields. Perhaps I would have better demonstrated the idea using an array of primitives instead of references...


In yet another words, given that a[i] is exposed already, you are facing seeing the racy update of
a[i] *after* you have stored/loaded the $array itself:

 Thread 1:                                  Thread 2:

 // --------------- Good case ------------------------------------------------------
   a[i] = o1;
   o1.x = 42; // unordered store
   array = a; // (*)
                                              a = array;
                                              o = a[i];
                                              assert (o.x == 42); // passes

 // --------------- Bad case ------------------------------------------------------

   a[i] = o2;
                                              a = array; // (**)
                                              o = a[i];
                                              assert (o.x == 43); // fails!
   o2.x = 43; // unordered store
   array = a;

Oops. The problem is, you might think that at (*) you are reading the store at (**), and that
provides you ordering guarantees, while in reality that gives you nothing in bad case, because the
racy update is happening nevertheless.

The way out without VarHandles or AtomicXXXArray-s is to "version" the array, increment the version
before and after updating the a[i], and and check if version had changed while we were reading the
a[i] in another thread, but that reinvents sequence locks. Which might be the answer for you:
optimistic StampedLock in get(), maybe?

I think that using anything more would defeat the purpose of not using any utilities (suppose I want to do something in low-level JDK which is used by those utilities an I want to prevent bootstrapping issues).

But I think that my example might be flawed nevertheless. I wanted to prevent hoisting of array reads out of loops, but then I realized that the following hypothetical optimization of some JIT might defeat that and may still satisfy JMM (for the purpose of this example, cached[A,O,I] are locals hoisted out of loop that calls into get(i) and doesn't call into set(i, o)):

    Object[] cachedA = null;
    Object cachedO = new Object();
    int cachedI = 0;

...

    public Object get(int i) {
        Object[] a;
        do {
            a = array; // read reference to array
        } while (a == null);

        if (a == cachedA && i == cachedI) {
            return cachedO;
        } else {
            cachedA = a;
            cachedI = i;
            return cachedO = a[i];   // read array slot
        }
    }

Is such transformation legal according to JMM? Could we argue that reading thread did not observe the volatile write of array if that array stayed the same and therefore is not obligated to order other accesses around such volatile read of array?

Regards,
Peter

_______________________________________________
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
|

Re: VolatileArray

JSR166 Concurrency mailing list
In reply to this post by JSR166 Concurrency mailing list
On 04/04/2018 01:04 PM, Peter Levart wrote:

> On 04/04/2018 12:20 PM, Aleksey Shipilev wrote:
>> On 04/04/2018 10:58 AM, Peter Levart via Concurrency-interest wrote:
>> The way out without VarHandles or AtomicXXXArray-s is to "version" the array, increment the version
>> before and after updating the a[i], and and check if version had changed while we were reading the
>> a[i] in another thread, but that reinvents sequence locks. Which might be the answer for you:
>> optimistic StampedLock in get(), maybe?
>
> I think that using anything more would defeat the purpose of not using any utilities (suppose I want
> to do something in low-level JDK which is used by those utilities an I want to prevent bootstrapping
> issues).

That means Unsafe is available, and you are golden! Just use whatever j.u.c classes are using. It is
hard to come by the bootstrapping problem that includes Unsafe not being available, given it is
~40-th primordial class loaded during bootstrapping at least in Hotspot.

> But I think that my example might be flawed nevertheless. I wanted to prevent hoisting of array
> reads out of loops,

Sorry, I missed that.

It is hard to reconcile the requirement for "not being hoisted from the loop" and generic JMM. If we
are looking for the answer in JMM terms, we have to pose the question in JMM terms. The trouble is
that progress guarantees are awkwardly-defined. So, I find it more productive to just use the blocks
that have higher-level semantics, and employ the rule-of-thumb that plain accesses have no progress
guarantees, while everything stronger has. And try not to thing to extend those progress guarantees
beyond the accesses *themselves*: e.g. make array element accesses with stronger ordering, not try
to piggyback on something else.

See the discussion here:
  http://gee.cs.oswego.edu/dl/html/j9mm.html

I suggest using VarHandles (or their relevant Unsafe entry points) over array elements to begin
with, and only then figure out bootstrapping problems that might or might not exist. If the desired
behavior can be relaxed to only progress guarantees (it is arguably safe when arrays in your example
are primitive), then out-of-JMM VarHandles opaque mode (similar to std::atomic mem_ord_relaxed) is
what you are looking for.

On the other hand, doing the super-constrained ultra-low-level work sometimes means doing the
implementation-specific assumptions. Doug does them sometimes in j.u.c. (and some people, weirdly,
take that as the guidance, pour souls). So, in current Hotspot, if Unsafe is not available, it seems
to be enough to make the particular sorts of (Object?) volatile reads / Unsafe calls (and store its
result somewhere on heap?) to break the loop-hoisting optimizations. But it is a super-fragile
assumption, and you should only use that as an absolutely last resort.

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

Re: VolatileArray

JSR166 Concurrency mailing list


----- Mail original -----
> De: "Aleksey Shipilev via Concurrency-interest" <[hidden email]>
> À: "Peter Levart" <[hidden email]>, [hidden email]
> Envoyé: Mercredi 4 Avril 2018 17:22:47
> Objet: Re: [concurrency-interest] VolatileArray

> On 04/04/2018 01:04 PM, Peter Levart wrote:
>> On 04/04/2018 12:20 PM, Aleksey Shipilev wrote:
>>> On 04/04/2018 10:58 AM, Peter Levart via Concurrency-interest wrote:
>>> The way out without VarHandles or AtomicXXXArray-s is to "version" the array,
>>> increment the version
>>> before and after updating the a[i], and and check if version had changed while
>>> we were reading the
>>> a[i] in another thread, but that reinvents sequence locks. Which might be the
>>> answer for you:
>>> optimistic StampedLock in get(), maybe?
>>
>> I think that using anything more would defeat the purpose of not using any
>> utilities (suppose I want
>> to do something in low-level JDK which is used by those utilities an I want to
>> prevent bootstrapping
>> issues).
>
> That means Unsafe is available, and you are golden! Just use whatever j.u.c
> classes are using. It is
> hard to come by the bootstrapping problem that includes Unsafe not being
> available, given it is
> ~40-th primordial class loaded during bootstrapping at least in Hotspot.

Just to be clear for everybody, Aleksey is talking about jdk.internal.misc.Unsafe and not sun.misc.Unsafe.

There are two 'Unsafe' now (since java 9),
- jdk.internal.misc.Unsafe is the one used by j.u.c and loaded early by the VM, but this class is not exported by the JDK, so can only be used inside the JDK,
- sun.misc.Unsafe that had already several methods deprecated and removed, that you can use at your own risk and that will be retired maybe one day.

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

Re: VolatileArray

JSR166 Concurrency mailing list
Opaque mode is the weakest form of access that promises progress, and is offered by Unsafe and VarHandle and Atomic*

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

Re: VolatileArray

JSR166 Concurrency mailing list
I think an immutable array would be more useful.

How many times do we clone an array, just to ensure we don't expose
internal state?

If you have a volatile reference and the array is immutable, you can
guarantee all changes to mutable state is atomic.

Too much mutable state is too hard to reason about, eg what if the
object you want to reference changes position in a mutable but volatile
element array?

Just my 20 cents.

Cheers,

Peter.

On 5/04/2018 8:23 AM, Martin Buchholz via Concurrency-interest wrote:
> Opaque mode is the weakest form of access that promises progress, and
> is offered by Unsafe and VarHandle and Atomic*
> http://gee.cs.oswego.edu/dl/html/j9mm.html#opaquesec
>
>
> _______________________________________________
> 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