[concurrency-interest] any read guarantees for static finals?

David Holmes davidcholmes at aapt.net.au
Thu Feb 9 15:17:37 EST 2012


JLS 12.4.2 explains the class initialization process in detail and states
that the lock (it isn't the Class instance's lock any more) must be acquired
and then the initialization state is checked. This means that every thread
must act as-if it does this for every class that it uses, and which must be
initialized for that use. This locking/unlocking enforces a happens-before
ordering as per any locking/unlocking. No inference or assumptions about
visibility are needed.

The VM can of course optimize this in a variety of ways, but it must always
act as-if the lock were acquired then released. JLS 12.4.3 alludes to this
when discussing code generation and the elision of initialization checks
when it is known that the class is already initialized.

David Holmes
  -----Original Message-----
  From: concurrency-interest-bounces at cs.oswego.edu
[mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Yuval Shavit
  Sent: Friday, 10 February 2012 5:16 AM
  To: Vitaly Davidovich
  Cc: concurrency-interest
  Subject: Re: [concurrency-interest] any read guarantees for static finals?


  Is it generally valid to make visibility assumptions on the JVM spec? I've
always been going by the JLS, which from what I understand is a bit looser
in its guarantees.


  JLS 12.4.2 does talk about class initialization in detail, and also
mentions a lock such that only one thread is allowed to init the class. That
said, if the class is already initialized, I don't see anything in the spec
that requires such a lock -- the details of answering "is this class already
initialized?" seems to be unspecified. So, it seems that if thread A
initializes the class, and some time later thread B uses the class for the
first time, there's nothing requiring thread B to try to initialize the
class, meaning there's no synchronization and no HB. Indeed, without that
behavior, every thread would be forced to acquire a lock at least once for
every class it sees, which would seem prohibitive.


  On Thu, Feb 9, 2012 at 1:42 PM, Vitaly Davidovich <vitalyd at gmail.com>
wrote:

    JVM spec 2.17.5 talks about static initialization in a bit of detail.
It doesn't explicitly mention memory visibility but it does make it clear
that a lock/unlock is associated with initialization such that only 1 thread
is allowed to init the class.  I think this implies that initializing writes
will be visible.

    Sent from my phone

    On Feb 9, 2012 1:27 PM, "Yuval Shavit" <yshavit at akiban.com> wrote:

      Where is that in the JLS? I can't find it (I'm looking especially at
17.4.5, "Happens-before Order").


      On Thu, Feb 9, 2012 at 12:48 PM, Vitaly Davidovich <vitalyd at gmail.com>
wrote:

        Static initialization guarantees visibility, so even without final
on the map it's guaranteed that all static initializing writes are seen
across cores (obviously subsequent writes to non-final non-volatile static
fields aren't guaranteed to be visible).

        Sent from my phone

        On Feb 9, 2012 12:32 PM, "Yuval Shavit" <yshavit at akiban.com> wrote:

          I've wondered this for a bit, and it finally came up in a
stackoverflow discussion recently. The JLS's description of final field read
semantics (as far as all threads seeing the state at least as it was at the
end of the constructor) only seems to apply to member fields -- not statics.
Specifically, JLS 17,5 refers only to object construction, not class
instantiation. JLS 13.4.9 states that primitives and Strings have to be seen
initialized, but makes no reference to other fields. So, are there actually
any guarantees for static finals?


          For instance, is this class thread-safe, given that it uses a
non-thread-safe map which is initialized statically and then never modified?


              import java.util.*;
              public class PoorMansEnum {
                  private static final Map<String,Integer> map =
createMap();

                  private static Map<String,Integer> createMap() {
                      Map<String,Integer> map = new
HashMap<String,Integer>();
                      map.put("Foo", 1);
                      map.put("Bar", 2);
                      return map;
                  }

                  public static int valueOf(String value) {
                      Integer integer = map.get(value);
                      if (integer == null)
                          throw new IllegalArgumentException("not a value: "
+ value);
                      return integer;
                  }
              }


          Is there even a guarantee that every thread will see a non-null
"map"? I can't find anything in the JLS about it.


          Thanks,
          -Yuval


          _______________________________________________
          Concurrency-interest mailing list
          Concurrency-interest at cs.oswego.edu
          http://cs.oswego.edu/mailman/listinfo/concurrency-interest





-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20120210/7388723d/attachment.html>


More information about the Concurrency-interest mailing list