Using a local variable when initializing a static variable











up vote
5
down vote

favorite












In the source code of java.util.Scanner I've found these static utility methods:



private static Pattern separatorPattern() {
Pattern sp = separatorPattern;
if (sp == null)
separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
return sp;
}

private static Pattern linePattern() {
Pattern lp = linePattern;
if (lp == null)
linePattern = lp = Pattern.compile(LINE_PATTERN);
return lp;
}


Why it was done in such a complex way and not just, say,



private static Pattern linePattern() {
if (linePattern == null)
linePattern = Pattern.compile(LINE_PATTERN);
return linePattern;
}


What was the point of using a local variable (lp) here? Is this some kind of optimization technique? Or maybe precaution against a concurrent modification? But linePattern cannot be set to null again as this method is the only place where it is modified.










share|improve this question


















  • 1




    It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
    – Dawood ibn Kareem
    Nov 20 at 23:58










  • Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
    – John McClane
    yesterday















up vote
5
down vote

favorite












In the source code of java.util.Scanner I've found these static utility methods:



private static Pattern separatorPattern() {
Pattern sp = separatorPattern;
if (sp == null)
separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
return sp;
}

private static Pattern linePattern() {
Pattern lp = linePattern;
if (lp == null)
linePattern = lp = Pattern.compile(LINE_PATTERN);
return lp;
}


Why it was done in such a complex way and not just, say,



private static Pattern linePattern() {
if (linePattern == null)
linePattern = Pattern.compile(LINE_PATTERN);
return linePattern;
}


What was the point of using a local variable (lp) here? Is this some kind of optimization technique? Or maybe precaution against a concurrent modification? But linePattern cannot be set to null again as this method is the only place where it is modified.










share|improve this question


















  • 1




    It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
    – Dawood ibn Kareem
    Nov 20 at 23:58










  • Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
    – John McClane
    yesterday













up vote
5
down vote

favorite









up vote
5
down vote

favorite











In the source code of java.util.Scanner I've found these static utility methods:



private static Pattern separatorPattern() {
Pattern sp = separatorPattern;
if (sp == null)
separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
return sp;
}

private static Pattern linePattern() {
Pattern lp = linePattern;
if (lp == null)
linePattern = lp = Pattern.compile(LINE_PATTERN);
return lp;
}


Why it was done in such a complex way and not just, say,



private static Pattern linePattern() {
if (linePattern == null)
linePattern = Pattern.compile(LINE_PATTERN);
return linePattern;
}


What was the point of using a local variable (lp) here? Is this some kind of optimization technique? Or maybe precaution against a concurrent modification? But linePattern cannot be set to null again as this method is the only place where it is modified.










share|improve this question













In the source code of java.util.Scanner I've found these static utility methods:



private static Pattern separatorPattern() {
Pattern sp = separatorPattern;
if (sp == null)
separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
return sp;
}

private static Pattern linePattern() {
Pattern lp = linePattern;
if (lp == null)
linePattern = lp = Pattern.compile(LINE_PATTERN);
return lp;
}


Why it was done in such a complex way and not just, say,



private static Pattern linePattern() {
if (linePattern == null)
linePattern = Pattern.compile(LINE_PATTERN);
return linePattern;
}


What was the point of using a local variable (lp) here? Is this some kind of optimization technique? Or maybe precaution against a concurrent modification? But linePattern cannot be set to null again as this method is the only place where it is modified.







java variables static initialization






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 at 23:52









John McClane

28311




28311








  • 1




    It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
    – Dawood ibn Kareem
    Nov 20 at 23:58










  • Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
    – John McClane
    yesterday














  • 1




    It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
    – Dawood ibn Kareem
    Nov 20 at 23:58










  • Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
    – John McClane
    yesterday








1




1




It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
– Dawood ibn Kareem
Nov 20 at 23:58




It's currently the only place where linePattern is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifying linePattern, which could cause concurrent modification problems in combination with (your version of) the code here.
– Dawood ibn Kareem
Nov 20 at 23:58












Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
– John McClane
yesterday




Just for the record. I've found a similar construct in java.util.Collections.shuffle(List<?> list). And there is a comment there: "harmless race". However, the static variable being initialized in that procedure is not volatile.
– John McClane
yesterday












2 Answers
2






active

oldest

votes

















up vote
3
down vote













I believe it's all about volatile keyword used with linePattern and separatorPattern fields



private static volatile Pattern separatorPattern;
private static volatile Pattern linePattern;


Due to specification




The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.



The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.



A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable




Also here we can read that




Declaring a volatile Java variable means:




  • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";


  • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.





That's why they firstly try to directly read field's value and then overwrite it with new value






share|improve this answer

















  • 1




    Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
    – John McClane
    Nov 21 at 2:04




















up vote
2
down vote













I think they want to avoid reading from the volatile field twice.




  • once to check if it is null

  • once for the return


In their version, they only




  • once read it into a local variable

  • confirm that the local variable is not null

  • return that local variable


The optimization is for the "happy path" that happens incredibly more often than the "initial setup path" that only happens once -- or at most a few times if the method is called concurrently before it has finished the initialization.




Or maybe precaution against a concurrent modification?




There is no such precaution. If you call linePattern concurrently before it has finished setting the static volatile field, the pattern will be created multiple times (but that's fine), different instances will be returned and a random one of those will be chosen to stick around (that's also fine, since they are equivalent).



Any measures to guard against that would only add cost to our "happy path" so should only be done in situations were the instance must really be a singleton for some reason.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403358%2fusing-a-local-variable-when-initializing-a-static-variable%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote













    I believe it's all about volatile keyword used with linePattern and separatorPattern fields



    private static volatile Pattern separatorPattern;
    private static volatile Pattern linePattern;


    Due to specification




    The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.



    The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.



    A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable




    Also here we can read that




    Declaring a volatile Java variable means:




    • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";


    • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.





    That's why they firstly try to directly read field's value and then overwrite it with new value






    share|improve this answer

















    • 1




      Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
      – John McClane
      Nov 21 at 2:04

















    up vote
    3
    down vote













    I believe it's all about volatile keyword used with linePattern and separatorPattern fields



    private static volatile Pattern separatorPattern;
    private static volatile Pattern linePattern;


    Due to specification




    The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.



    The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.



    A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable




    Also here we can read that




    Declaring a volatile Java variable means:




    • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";


    • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.





    That's why they firstly try to directly read field's value and then overwrite it with new value






    share|improve this answer

















    • 1




      Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
      – John McClane
      Nov 21 at 2:04















    up vote
    3
    down vote










    up vote
    3
    down vote









    I believe it's all about volatile keyword used with linePattern and separatorPattern fields



    private static volatile Pattern separatorPattern;
    private static volatile Pattern linePattern;


    Due to specification




    The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.



    The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.



    A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable




    Also here we can read that




    Declaring a volatile Java variable means:




    • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";


    • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.





    That's why they firstly try to directly read field's value and then overwrite it with new value






    share|improve this answer












    I believe it's all about volatile keyword used with linePattern and separatorPattern fields



    private static volatile Pattern separatorPattern;
    private static volatile Pattern linePattern;


    Due to specification




    The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.



    The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.



    A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable




    Also here we can read that




    Declaring a volatile Java variable means:




    • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";


    • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.





    That's why they firstly try to directly read field's value and then overwrite it with new value







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 21 at 0:01









    m.antkowicz

    8,380928




    8,380928








    • 1




      Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
      – John McClane
      Nov 21 at 2:04
















    • 1




      Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
      – John McClane
      Nov 21 at 2:04










    1




    1




    Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
    – John McClane
    Nov 21 at 2:04






    Assuming my variant of linePattern(), even if the variable linePattern gets modified by another thread right after linePattern = Pattern.compile(LINE_PATTERN); and before return linePattern;, the method will (precisely because of the volatile keyword) return a new value of linePattern, which is safe to use. That said, I don't see a reason to use the local variable lp.
    – John McClane
    Nov 21 at 2:04














    up vote
    2
    down vote













    I think they want to avoid reading from the volatile field twice.




    • once to check if it is null

    • once for the return


    In their version, they only




    • once read it into a local variable

    • confirm that the local variable is not null

    • return that local variable


    The optimization is for the "happy path" that happens incredibly more often than the "initial setup path" that only happens once -- or at most a few times if the method is called concurrently before it has finished the initialization.




    Or maybe precaution against a concurrent modification?




    There is no such precaution. If you call linePattern concurrently before it has finished setting the static volatile field, the pattern will be created multiple times (but that's fine), different instances will be returned and a random one of those will be chosen to stick around (that's also fine, since they are equivalent).



    Any measures to guard against that would only add cost to our "happy path" so should only be done in situations were the instance must really be a singleton for some reason.






    share|improve this answer



























      up vote
      2
      down vote













      I think they want to avoid reading from the volatile field twice.




      • once to check if it is null

      • once for the return


      In their version, they only




      • once read it into a local variable

      • confirm that the local variable is not null

      • return that local variable


      The optimization is for the "happy path" that happens incredibly more often than the "initial setup path" that only happens once -- or at most a few times if the method is called concurrently before it has finished the initialization.




      Or maybe precaution against a concurrent modification?




      There is no such precaution. If you call linePattern concurrently before it has finished setting the static volatile field, the pattern will be created multiple times (but that's fine), different instances will be returned and a random one of those will be chosen to stick around (that's also fine, since they are equivalent).



      Any measures to guard against that would only add cost to our "happy path" so should only be done in situations were the instance must really be a singleton for some reason.






      share|improve this answer

























        up vote
        2
        down vote










        up vote
        2
        down vote









        I think they want to avoid reading from the volatile field twice.




        • once to check if it is null

        • once for the return


        In their version, they only




        • once read it into a local variable

        • confirm that the local variable is not null

        • return that local variable


        The optimization is for the "happy path" that happens incredibly more often than the "initial setup path" that only happens once -- or at most a few times if the method is called concurrently before it has finished the initialization.




        Or maybe precaution against a concurrent modification?




        There is no such precaution. If you call linePattern concurrently before it has finished setting the static volatile field, the pattern will be created multiple times (but that's fine), different instances will be returned and a random one of those will be chosen to stick around (that's also fine, since they are equivalent).



        Any measures to guard against that would only add cost to our "happy path" so should only be done in situations were the instance must really be a singleton for some reason.






        share|improve this answer














        I think they want to avoid reading from the volatile field twice.




        • once to check if it is null

        • once for the return


        In their version, they only




        • once read it into a local variable

        • confirm that the local variable is not null

        • return that local variable


        The optimization is for the "happy path" that happens incredibly more often than the "initial setup path" that only happens once -- or at most a few times if the method is called concurrently before it has finished the initialization.




        Or maybe precaution against a concurrent modification?




        There is no such precaution. If you call linePattern concurrently before it has finished setting the static volatile field, the pattern will be created multiple times (but that's fine), different instances will be returned and a random one of those will be chosen to stick around (that's also fine, since they are equivalent).



        Any measures to guard against that would only add cost to our "happy path" so should only be done in situations were the instance must really be a singleton for some reason.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 21 at 3:02

























        answered Nov 21 at 2:55









        Thilo

        191k76410566




        191k76410566






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403358%2fusing-a-local-variable-when-initializing-a-static-variable%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Berounka

            Sphinx de Gizeh

            Different font size/position of beamer's navigation symbols template's content depending on regular/plain...