67 lines
1.5 KiB
Plaintext
67 lines
1.5 KiB
Plaintext
Double-checked locking can be used for lazy initialization of ``++volatile++`` fields, but only if field assignment is the last step in the ``++synchronized++`` block. Otherwise you run the risk of threads accessing a half-initialized object.
|
|
|
|
|
|
== Noncompliant Code Example
|
|
|
|
----
|
|
public class MyClass {
|
|
|
|
private volatile List<String> strings;
|
|
|
|
public List<String> getStrings() {
|
|
if (strings == null) { // check#1
|
|
synchronized(MyClass.class) {
|
|
if (strings == null) {
|
|
strings = new ArrayList<>(); // Noncompliant
|
|
strings.add("Hello"); //When threadA gets here, threadB can skip the synchronized block because check#1 is false
|
|
strings.add("World");
|
|
}
|
|
}
|
|
}
|
|
return strings;
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== Compliant Solution
|
|
|
|
----
|
|
public class MyClass {
|
|
|
|
private volatile List<String> strings;
|
|
|
|
public List<String> getStrings() {
|
|
if (strings == null) { // check#1
|
|
synchronized(MyClass.class) {
|
|
if (strings == null) {
|
|
List<String> tmpList = new ArrayList<>();
|
|
tmpList.add("Hello");
|
|
tmpList.add("World");
|
|
strings = tmpList;
|
|
}
|
|
}
|
|
}
|
|
return strings;
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== See
|
|
|
|
* https://wiki.sei.cmu.edu/confluence/x/6zdGBQ[CERT, LCK10-J.] - Use a correct form of the double-checked locking idiom
|
|
|
|
=== See Also
|
|
|
|
* S2168 - Double-checked locking should not be used
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::comments-and-links.adoc[]
|
|
endif::env-github,rspecator-view[]
|