Explicitly initializing volatile fields with default values

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

Explicitly initializing volatile fields with default values

Aleksey Shipilev-2
Hi there, concurrency dwellers,

I'm trying to find a counter-example/constraints against removing the
field initializers for volatile fields, when those initializers are
storing the default value. We know this improves performance, e.g.
  https://bugs.openjdk.java.net/browse/JDK-8035284

There is a gut feeling that removing these initializations is safe. But,
I have heard rumors of traces of counter-examples in OpenJDK bugtracker,
but found nothing substantial, which gives me doubts. Maybe there are
constraints I am overlooking?

First, let me show that you cannot (always) do this mechanically for all
(even non-volatile!) usages. JLS 8.3.2.3 "Restrictions on the use of
Fields during Initialization" allows this:

public class InitializerOverwrite {
  {
    x1 = 42;
    x2 = 42;
  }

  int x1;
  int x2 = 0;

  public static void main(String... args) {
    InitializerOverwrite io = new InitializerOverwrite();
    System.out.println(io.x1); // 42
    System.out.println(io.x2); // 0
  }
}

...so you definitely need to inspect if there is some stray store that
needs to be stamped out with the field initializer. What's worse,
instance/field initializer can invoke an arbitrary method that might
confuse any analysis, but still perform an instance field store. So, we
can reliably do this optimization for simple cases only.

But let's consider a simpler case for concurrency implications:

 class C {
   volatile int v = 0; // can we drop " = 0"?

   public C() {
     // nothing here
   }
 }

Is there a plausible case that shows the semantical difference with
field initializer storing a default value, and without one, that does
*not* also affect single-threaded usages (i.e. it does not follow from
the instance initialization sequence itself)?

Naive attempts to construct the examples seem to boil down to two cases.

*** Case A. Over-reaching "memory effects" for instance fields:

 class A {
   int f;
   volatile int v = 0;

   public A() {
     f = 42;
   }
 }

 A global;

 ----

 Thread 1:
   global = new A();

 Thread 2:
   A a = global;
   if (a != null && a.v == 0) {
     print(a.f); // ?
   }

There are no guarantees here whatsoever, because field initializations
are performed *before* any constructor body starts, as per JLS 12.5.
Therefore, the "releasing" volatile store to $v is executed before any
store to $f, which deconstructs any happens-before.

This seems to expand to non-instance fields, and other variables written
after firing the field initializer.

Note, that perhaps moving the initialization ($v = 0) into the
constructor after ($f = 42), or, similarly, making ($f = 42) the field
initializer, would lay out the code in the correct shape, and this gets
us to case B.


*** Case B. Transitive "memory effects" over explicit stores:

 class B {
   int f = 42;
   volatile int v = 0;
 }

 B global;

 ----

 Thread 1:
   global = new B();

 Thread 2:
   B b = global;
   if (b != null && b.v == 0) {
     print(b.f); // ?
   }

These three executions seem plausible:

 1) Happens-before read of write(f, 42):

  (default) write(v,0)
  (default) write(f,0)
         |
         | hb/sw
         v
     write(f,42) --hb/po--> write(v,0)
                                |
                                | hb/sw
                                v
                             read(v):0 --hb/po--> read(f):42;

 2) Read of default write(f, 0) -- these synchronize-with the first
action in the thread:

                       (default) write(v,0)
                       (default) write(f,0)
                                |
                                | hb/sw
                                v
                             read(v):0 --hb/po--> read(f):0

 (One might wonder if that means you can see the default value for an
explicitly initialized volatile field, once you read the instance itself
-- you can! -- we have seen this with AtomicIntegers before)

 3) Racy read of unordered write(f, 42):

     (default) write(v,0)
     (default) write(f,0)          write(f, 42)
                  |                     .
                  | hb/sw               . (unordered)
                  v                     .
               read(v):0 --hb/po--> read(f):42


In other words, if we drop execution (1) by omitting the explicit
initializing store, we would still be able to observe both "0" and "42".

This seems to expand to non-instance fields, and other variables written
before firing the field initializer.

*** Putting all together

Now, putting these things together:

 * Case A tells that no variable written *after* the volatile instance
field initializer is protected (duh).

 * Case B tells that no variable written *before* the volatile instance
field initializer writing the default value is protected by
happens-before. This is because the explicit initializing store with the
default value is indistinguishable from the default value store.

 * Since Case A and Case B cover all possible variables (with the
exception of the volatile field itself), this seems to imply that
explicit field initializers that store default values have no effect on
memory ordering.

Is it a correct way to think about it?

Thanks,
-Aleksey


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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Vitaly Davidovich


On Thursday, December 17, 2015, Aleksey Shipilev <[hidden email]> wrote:
Hi there, concurrency dwellers,

I'm trying to find a counter-example/constraints against removing the
field initializers for volatile fields, when those initializers are
storing the default value. We know this improves performance, e.g.
  https://bugs.openjdk.java.net/browse/JDK-8035284

There is a gut feeling that removing these initializations is safe. But,
I have heard rumors of traces of counter-examples in OpenJDK bugtracker,
but found nothing substantial, which gives me doubts. Maybe there are
constraints I am overlooking?

First, let me show that you cannot (always) do this mechanically for all
(even non-volatile!) usages. JLS 8.3.2.3 "Restrictions on the use of
Fields during Initialization" allows this:

public class InitializerOverwrite {
  {
    x1 = 42;
    x2 = 42;
  }

  int x1;
  int x2 = 0;

  public static void main(String... args) {
    InitializerOverwrite io = new InitializerOverwrite();
    System.out.println(io.x1); // 42
    System.out.println(io.x2); // 0
  }
}

...so you definitely need to inspect if there is some stray store that
needs to be stamped out with the field initializer. What's worse,
instance/field initializer can invoke an arbitrary method that might
confuse any analysis, but still perform an instance field store. So, we
can reliably do this optimization for simple cases only.

But let's consider a simpler case for concurrency implications:

 class C {
   volatile int v = 0; // can we drop " = 0"?

   public C() {
     // nothing here
   }
 }

Is there a plausible case that shows the semantical difference with
field initializer storing a default value, and without one, that does
*not* also affect single-threaded usages (i.e. it does not follow from
the instance initialization sequence itself)?

Naive attempts to construct the examples seem to boil down to two cases.

*** Case A. Over-reaching "memory effects" for instance fields:

 class A {
   int f;
   volatile int v = 0;

   public A() {
     f = 42;
   }
 }

 A global;

 ----

 Thread 1:
   global = new A();

 Thread 2:
   A a = global;
   if (a != null && a.v == 0) {
     print(a.f); // ?
   }

There are no guarantees here whatsoever, because field initializations
are performed *before* any constructor body starts, as per JLS 12.5.
Therefore, the "releasing" volatile store to $v is executed before any
store to $f, which deconstructs any happens-before.

This seems to expand to non-instance fields, and other variables written
after firing the field initializer.

Note, that perhaps moving the initialization ($v = 0) into the
constructor after ($f = 42), or, similarly, making ($f = 42) the field
initializer, would lay out the code in the correct shape, and this gets
us to case B.


*** Case B. Transitive "memory effects" over explicit stores:

 class B {
   int f = 42;
   volatile int v = 0;
 }

 B global;

 ----

 Thread 1:
   global = new B();

 Thread 2:
   B b = global;
   if (b != null && b.v == 0) {
     print(b.f); // ?
   }

These three executions seem plausible:

 1) Happens-before read of write(f, 42):

  (default) write(v,0)
  (default) write(f,0)
         |
         | hb/sw
         v
     write(f,42) --hb/po--> write(v,0)
                                |
                                | hb/sw
                                v
                             read(v):0 --hb/po--> read(f):42;

 2) Read of default write(f, 0) -- these synchronize-with the first
action in the thread:

                       (default) write(v,0)
                       (default) write(f,0)
                                |
                                | hb/sw
                                v
                             read(v):0 --hb/po--> read(f):0

 (One might wonder if that means you can see the default value for an
explicitly initialized volatile field, once you read the instance itself
-- you can! -- we have seen this with AtomicIntegers before)

Aren't instance fields initialized in textual order according to JLS? It's not clear to me how this would be allowed.  In particular, if volatile writes in ctor are supposed to have same ordering constraints as final field writes (that's supposedly going to be stated in next JMM revision), how was it possible to see AtomicInteger field with default value?

 

 3) Racy read of unordered write(f, 42):

     (default) write(v,0)
     (default) write(f,0)          write(f, 42)
                  |                     .
                  | hb/sw               . (unordered)
                  v                     .
               read(v):0 --hb/po--> read(f):42


In other words, if we drop execution (1) by omitting the explicit
initializing store, we would still be able to observe both "0" and "42".

This seems to expand to non-instance fields, and other variables written
before firing the field initializer.

*** Putting all together

Now, putting these things together:

 * Case A tells that no variable written *after* the volatile instance
field initializer is protected (duh).

 * Case B tells that no variable written *before* the volatile instance
field initializer writing the default value is protected by
happens-before. This is because the explicit initializing store with the
default value is indistinguishable from the default value store.

 * Since Case A and Case B cover all possible variables (with the
exception of the volatile field itself), this seems to imply that
explicit field initializers that store default values have no effect on
memory ordering.

Is it a correct way to think about it?

Thanks,
-Aleksey



--
Sent from my phone

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

Re: Explicitly initializing volatile fields with default values

Aleksey Shipilev-2
On 12/18/2015 03:06 AM, Vitaly Davidovich wrote:

> On Thursday, December 17, 2015, Aleksey Shipilev
>      2) Read of default write(f, 0) -- these synchronize-with the first
>     action in the thread:
>
>                            (default) write(v,0)
>                            (default) write(f,0)
>                                     |
>                                     | hb/sw
>                                     v
>                                  read(v):0 --hb/po--> read(f):0
>
>      (One might wonder if that means you can see the default value for an
>     explicitly initialized volatile field, once you read the instance itself
>     -- you can! -- we have seen this with AtomicIntegers before)
>
> Aren't instance fields initialized in textual order according to JLS?
Instance field initializers and instance initializers are run in the
lexical order, but this is irrelevant for:

> It's not clear to me how this would be allowed.  In particular, if
> volatile writes in ctor are supposed to have same ordering constraints
> as final field writes (that's supposedly going to be stated in next JMM
> revision), how was it possible to see AtomicInteger field with default
> value?

Volatile writes in constructors *are not* having the same ordering
constraints as final field writes. Some implementations might choose to
provide final-like behavior today, but it is not required by spec.

That remark was not supposed to re-fuel the discussion on volatile
writes in constructors themselves -- we seem to agree that's a problem,
we know that should be addressed in JMM update. Interested readers are
welcome to re-read the entire thread from the last time:

http://cs.oswego.edu/pipermail/concurrency-interest/2013-November/011954.html

But here, let's try to discuss the original "problem" with volatile
field initializers storing the default values with the current formal spec.

Thanks,
-Aleksey



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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Doug Lea
In reply to this post by Aleksey Shipilev-2
On 12/17/2015 04:36 PM, Aleksey Shipilev wrote:

>   * Since Case A and Case B cover all possible variables (with the
> exception of the volatile field itself), this seems to imply that
> explicit field initializers that store default values have no effect on
> memory ordering.
>
> Is it a correct way to think about it?
>

Yes. Without a machine-checkable JLS and JMM formalization, it's hard to prove
this definitively. But your account is a more careful version of reasoning
we've done before to conclude that there is never any reason to explicitly
initialize fields to 0/0.0/false/null. (There might be traces of these
discussions in the original JSR133 mail archives.)

Some people like to explicitly initialize to 0/0.0/false/null for clarity.
Arguably javac should not penalize this by generating unnecessary code.

-Doug


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

Re: Explicitly initializing volatile fields with default values

thurstonn
In reply to this post by Aleksey Shipilev-2
What about


class B
{
    int f = 42;
    boolean initialized = true;
    volatile int v = 0;


}

B global;

Thread 1:
   global = new B();

 Thread 2:
   B b = global;
   if (b != null && b.initialized && b.v == 0) {
     print(b.f); // ?
   }

I still think that the JMM allows either 0 or 42.

"There is a gut feeling that removing these initializations is safe"

But partly it comes down to your definition of "safe", i.e.

1.  Safe ==> spec-compliant
or
2.  Safe ==> no JVM presently in use will behave differently in the face of initialization-to-default-value elision


Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Justin Sampson
In reply to this post by Doug Lea
Doug Lea wrote:

> Yes. Without a machine-checkable JLS and JMM formalization, it's
> hard to prove this definitively. But your account is a more
> careful version of reasoning we've done before to conclude that
> there is never any reason to explicitly initialize fields to
> 0/0.0/false/null. (There might be traces of these discussions in
> the original JSR133 mail archives.)

This seems like a specific instance of the more general question of
whether _any_ volatile write has visible memory ordering effects if
it doesn't actually change the value stored in memory. I remember a
discussion touching on that question back in January regarding the
semantics of a failed or no-op compareAndSet. Since the value is not
changed, there is no way for another thread to notice that anything
has happened, and therefore no other thread can _depend_ on any such
memory ordering effects for correctness -- at least in practical
terms, even if some specific executions happen to be ruled out.

That thread was "Varieties of CAS semantics" here:

http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/thread.html#13613

Cheers,
Justin

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

Re: Explicitly initializing volatile fields with default values

Aleksey Shipilev-2
In reply to this post by thurstonn
On 12/18/2015 04:30 AM, thurstonn wrote:

> class B
> {
>     int f = 42;
>     boolean initialized = true;
>     volatile int v = 0;
>
>
> }
>
> B global;
>
> Thread 1:
>    global = new B();
>
>  Thread 2:
>    B b = global;
>    if (b != null && b.initialized && b.v == 0) {
>      print(b.f); // ?
>    }
>
> I still think that the JMM allows either 0 or 42.
Yes, it does. I don't see how this case differs from the original case
without the "initialized" field. Moreover, since the $initialized read
is done before "acquiring" $v read, there is no effect whatsoever ;)


> "There is a gut feeling that removing these initializations is *safe*"
>
> But partly it comes down to your definition of "safe", i.e.
>
> 1.  Safe ==> spec-compliant
> or
> 2.  Safe ==> no JVM presently in use will behave differently in the face of
> initialization-to-default-value elision

I tried to frame a more formal question in the original note:

"Is there a plausible case that shows the semantical difference with
field initializer storing a default value, and without one, that does
*not* also affect single-threaded usages (i.e. it does not follow from
the instance initialization sequence itself)?"

The answer to which is, apparently, "no".

Thanks,
-Aleksey



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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Aleksey Shipilev-2
In reply to this post by Justin Sampson
On 12/18/2015 05:11 AM, Justin Sampson wrote:
> Doug Lea wrote:
>
>> Yes. Without a machine-checkable JLS and JMM formalization, it's
>> hard to prove this definitively. But your account is a more
>> careful version of reasoning we've done before to conclude that
>> there is never any reason to explicitly initialize fields to
>> 0/0.0/false/null. (There might be traces of these discussions in
>> the original JSR133 mail archives.)

Excellent, then we will go forward with pruning stray volatile stores
with default values from JDK:
 https://bugs.openjdk.java.net/browse/JDK-6736490
 https://bugs.openjdk.java.net/browse/JDK-8145680


> This seems like a specific instance of the more general question of
> whether _any_ volatile write has visible memory ordering effects if
> it doesn't actually change the value stored in memory. I remember a
> discussion touching on that question back in January regarding the
> semantics of a failed or no-op compareAndSet. Since the value is not
> changed, there is no way for another thread to notice that anything
> has happened, and therefore no other thread can _depend_ on any such
> memory ordering effects for correctness -- at least in practical
> terms, even if some specific executions happen to be ruled out.

Indeed, this default values case seems to be a special subcase of that
general observation.


> That thread was "Varieties of CAS semantics" here:
>
> http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/thread.html#13613

Thanks! Good read.

Cheers,
-Aleksey


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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

thurstonn
In reply to this post by Aleksey Shipilev-2
Aleksey Shipilev-2 wrote
On 12/18/2015 04:30 AM, thurstonn wrote:
> class B
> {
>     int f = 42;
>     boolean initialized = true;
>     volatile int v = 0;
>
>
> }
>
> B global;
>
> Thread 1:
>    global = new B();
>
>  Thread 2:
>    B b = global;
>    if (b != null && b.initialized && b.v == 0) {
>      print(b.f); // ?
>    }
>
> I still think that the JMM allows either 0 or 42.

Yes, it does. I don't see how this case differs from the original case
without the "initialized" field. Moreover, since the $initialized read
is done before "acquiring" $v read, there is no effect whatsoever ;)
The order of the $initialized read wrt to the $v read is irrelevant to the point I was making, i.e. if the code was:

if (b != null && b.v == 0 && b.initialized)
{
      print(b.f); // ?
}
the point would be the same.
Why?  because we're in agreement that no synchronizes-with edge can be deduced from the program, so in terms of the JMM (which is what I meant by spec-compliance),
<r(initialized), T2, true> tells you nothing about
<r(f), T2, ?>


But in reference to definition of "safe" (#2 below) compare:

1.  Elide the initializing write of $v
  vs.
2.  There is some store fence emitted between the initializing write to $initialized = true and $v=0

I was merely positing on some platform(s),
in case 1 ==>
<r(initialized), T2, true> tells you nothing about
<r(f), T2, ?>

but in case 2 ==>
<r(initialized), T2, true> always results in:
<r(f), T2, 42>

again, not as dictated by the JMM, but by a particular platform's implementation/behavior of the JMM; producing a stronger memory model than required.

If such a platform exists, then eliding the initializing $v = 0, hence eliding the store fence (#1 above), changes the possible results of program executions (which would be "unsafe" in the sense of #2 below)








> "There is a gut feeling that removing these initializations is *safe*"
>
> But partly it comes down to your definition of "safe", i.e.
>
> 1.  Safe ==> spec-compliant
> or
> 2.  Safe ==> no JVM presently in use will behave differently in the face of
> initialization-to-default-value elision

I tried to frame a more formal question in the original note:

"Is there a plausible case that shows the semantical difference with
field initializer storing a default value, and without one, that does
*not* also affect single-threaded usages (i.e. it does not follow from
the instance initialization sequence itself)?"

The answer to which is, apparently, "no".

Thanks,
-Aleksey



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


signature.asc (836 bytes) <http://jsr166-concurrency.10961.n7.nabble.com/attachment/13100/0/signature.asc>

Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Alex Otenko
In reply to this post by Aleksey Shipilev-2
So, you are considering what the legitimate outcomes of a racy publication are, right? Since global in both cases is not volatile, I am not sure I understand the purpose of specifying a “correct” initialization visibility order for values published in a way we discourage as error-prone. Do we have legitimate code that uses racy publication of this sort?

Alex

> On 17 Dec 2015, at 21:36, Aleksey Shipilev <[hidden email]> wrote:
>
> Hi there, concurrency dwellers,
>
> I'm trying to find a counter-example/constraints against removing the
> field initializers for volatile fields, when those initializers are
> storing the default value. We know this improves performance, e.g.
>  https://bugs.openjdk.java.net/browse/JDK-8035284
>
> There is a gut feeling that removing these initializations is safe. But,
> I have heard rumors of traces of counter-examples in OpenJDK bugtracker,
> but found nothing substantial, which gives me doubts. Maybe there are
> constraints I am overlooking?
>
> First, let me show that you cannot (always) do this mechanically for all
> (even non-volatile!) usages. JLS 8.3.2.3 "Restrictions on the use of
> Fields during Initialization" allows this:
>
> public class InitializerOverwrite {
>  {
>    x1 = 42;
>    x2 = 42;
>  }
>
>  int x1;
>  int x2 = 0;
>
>  public static void main(String... args) {
>    InitializerOverwrite io = new InitializerOverwrite();
>    System.out.println(io.x1); // 42
>    System.out.println(io.x2); // 0
>  }
> }
>
> ...so you definitely need to inspect if there is some stray store that
> needs to be stamped out with the field initializer. What's worse,
> instance/field initializer can invoke an arbitrary method that might
> confuse any analysis, but still perform an instance field store. So, we
> can reliably do this optimization for simple cases only.
>
> But let's consider a simpler case for concurrency implications:
>
> class C {
>   volatile int v = 0; // can we drop " = 0"?
>
>   public C() {
>     // nothing here
>   }
> }
>
> Is there a plausible case that shows the semantical difference with
> field initializer storing a default value, and without one, that does
> *not* also affect single-threaded usages (i.e. it does not follow from
> the instance initialization sequence itself)?
>
> Naive attempts to construct the examples seem to boil down to two cases.
>
> *** Case A. Over-reaching "memory effects" for instance fields:
>
> class A {
>   int f;
>   volatile int v = 0;
>
>   public A() {
>     f = 42;
>   }
> }
>
> A global;
>
> ----
>
> Thread 1:
>   global = new A();
>
> Thread 2:
>   A a = global;
>   if (a != null && a.v == 0) {
>     print(a.f); // ?
>   }
>
> There are no guarantees here whatsoever, because field initializations
> are performed *before* any constructor body starts, as per JLS 12.5.
> Therefore, the "releasing" volatile store to $v is executed before any
> store to $f, which deconstructs any happens-before.
>
> This seems to expand to non-instance fields, and other variables written
> after firing the field initializer.
>
> Note, that perhaps moving the initialization ($v = 0) into the
> constructor after ($f = 42), or, similarly, making ($f = 42) the field
> initializer, would lay out the code in the correct shape, and this gets
> us to case B.
>
>
> *** Case B. Transitive "memory effects" over explicit stores:
>
> class B {
>   int f = 42;
>   volatile int v = 0;
> }
>
> B global;
>
> ----
>
> Thread 1:
>   global = new B();
>
> Thread 2:
>   B b = global;
>   if (b != null && b.v == 0) {
>     print(b.f); // ?
>   }
>
> These three executions seem plausible:
>
> 1) Happens-before read of write(f, 42):
>
>  (default) write(v,0)
>  (default) write(f,0)
>         |
>         | hb/sw
>         v
>     write(f,42) --hb/po--> write(v,0)
>                                |
>                                | hb/sw
>                                v
>                             read(v):0 --hb/po--> read(f):42;
>
> 2) Read of default write(f, 0) -- these synchronize-with the first
> action in the thread:
>
>                       (default) write(v,0)
>                       (default) write(f,0)
>                                |
>                                | hb/sw
>                                v
>                             read(v):0 --hb/po--> read(f):0
>
> (One might wonder if that means you can see the default value for an
> explicitly initialized volatile field, once you read the instance itself
> -- you can! -- we have seen this with AtomicIntegers before)
>
> 3) Racy read of unordered write(f, 42):
>
>     (default) write(v,0)
>     (default) write(f,0)          write(f, 42)
>                  |                     .
>                  | hb/sw               . (unordered)
>                  v                     .
>               read(v):0 --hb/po--> read(f):42
>
>
> In other words, if we drop execution (1) by omitting the explicit
> initializing store, we would still be able to observe both "0" and "42".
>
> This seems to expand to non-instance fields, and other variables written
> before firing the field initializer.
>
> *** Putting all together
>
> Now, putting these things together:
>
> * Case A tells that no variable written *after* the volatile instance
> field initializer is protected (duh).
>
> * Case B tells that no variable written *before* the volatile instance
> field initializer writing the default value is protected by
> happens-before. This is because the explicit initializing store with the
> default value is indistinguishable from the default value store.
>
> * Since Case A and Case B cover all possible variables (with the
> exception of the volatile field itself), this seems to imply that
> explicit field initializers that store default values have no effect on
> memory ordering.
>
> Is it a correct way to think about it?
>
> Thanks,
> -Aleksey
>
> _______________________________________________
> 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: Explicitly initializing volatile fields with default values

Aleksey Shipilev-2
On 01/04/2016 01:34 PM, Alex Otenko wrote:
> So, you are considering what the legitimate outcomes of a racy
> publication are, right? Since global in both cases is not volatile, I
> am not sure I understand the purpose of specifying a “correct”
> initialization visibility order for values published in a way we
> discourage as error-prone. Do we have legitimate code that uses racy
> publication of this sort?

When considering a bulk update in a class library, it is pragmatic to
understand if any new behaviors are possible, even if they are within
the realm of current spec. Because the alternative would be reviewing
each and any usage for "surprising" but legitimate code examples.

Thanks,
-Aleksey


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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Explicitly initializing volatile fields with default values

Alex Otenko
ok, I see your point.

Even though I think in the end the surprising behaviours will be down to underspecified outcomes and specific JVM implementations.

Alex

> On 11 Jan 2016, at 11:05, Aleksey Shipilev <[hidden email]> wrote:
>
> On 01/04/2016 01:34 PM, Alex Otenko wrote:
>> So, you are considering what the legitimate outcomes of a racy
>> publication are, right? Since global in both cases is not volatile, I
>> am not sure I understand the purpose of specifying a “correct”
>> initialization visibility order for values published in a way we
>> discourage as error-prone. Do we have legitimate code that uses racy
>> publication of this sort?
>
> When considering a bulk update in a class library, it is pragmatic to
> understand if any new behaviors are possible, even if they are within
> the realm of current spec. Because the alternative would be reviewing
> each and any usage for "surprising" but legitimate code examples.
>
> Thanks,
> -Aleksey
>


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