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.
java variables static initialization
add a comment |
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.
java variables static initialization
1
It's currently the only place wherelinePattern
is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifyinglinePattern
, 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 injava.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
add a comment |
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.
java variables static initialization
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
java variables static initialization
asked Nov 20 at 23:52
John McClane
28311
28311
1
It's currently the only place wherelinePattern
is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifyinglinePattern
, 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 injava.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
add a comment |
1
It's currently the only place wherelinePattern
is modified. But Oracle are very good at writing code that's future-proof. Maybe a future JDK version will have another way of modifyinglinePattern
, 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 injava.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
add a comment |
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
1
Assuming my variant oflinePattern()
, even if the variablelinePattern
gets modified by another thread right afterlinePattern = Pattern.compile(LINE_PATTERN);
and beforereturn linePattern;
, the method will (precisely because of thevolatile
keyword) return a new value oflinePattern
, which is safe to use. That said, I don't see a reason to use the local variablelp
.
– John McClane
Nov 21 at 2:04
add a comment |
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.
add a comment |
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
1
Assuming my variant oflinePattern()
, even if the variablelinePattern
gets modified by another thread right afterlinePattern = Pattern.compile(LINE_PATTERN);
and beforereturn linePattern;
, the method will (precisely because of thevolatile
keyword) return a new value oflinePattern
, which is safe to use. That said, I don't see a reason to use the local variablelp
.
– John McClane
Nov 21 at 2:04
add a comment |
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
1
Assuming my variant oflinePattern()
, even if the variablelinePattern
gets modified by another thread right afterlinePattern = Pattern.compile(LINE_PATTERN);
and beforereturn linePattern;
, the method will (precisely because of thevolatile
keyword) return a new value oflinePattern
, which is safe to use. That said, I don't see a reason to use the local variablelp
.
– John McClane
Nov 21 at 2:04
add a comment |
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
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
answered Nov 21 at 0:01
m.antkowicz
8,380928
8,380928
1
Assuming my variant oflinePattern()
, even if the variablelinePattern
gets modified by another thread right afterlinePattern = Pattern.compile(LINE_PATTERN);
and beforereturn linePattern;
, the method will (precisely because of thevolatile
keyword) return a new value oflinePattern
, which is safe to use. That said, I don't see a reason to use the local variablelp
.
– John McClane
Nov 21 at 2:04
add a comment |
1
Assuming my variant oflinePattern()
, even if the variablelinePattern
gets modified by another thread right afterlinePattern = Pattern.compile(LINE_PATTERN);
and beforereturn linePattern;
, the method will (precisely because of thevolatile
keyword) return a new value oflinePattern
, which is safe to use. That said, I don't see a reason to use the local variablelp
.
– 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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited Nov 21 at 3:02
answered Nov 21 at 2:55
Thilo
191k76410566
191k76410566
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 modifyinglinePattern
, 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