diff --git a/docs/config_misc.html b/docs/config_misc.html
index a92a439c5..957f2275f 100644
--- a/docs/config_misc.html
+++ b/docs/config_misc.html
@@ -70,6 +70,9 @@
FinalParameters
+
+ DoubleCheckedLocking
+
@@ -787,6 +790,52 @@ public class StringUtils // not final to allow subclassing
TreeWalker
+ DoubleCheckedLocking
Description
+
+ The "double-checked locking" idiom (DCL) tries to avoid the runtime cost
+ of synchronization. An example that uses the DCL idiom is this:
+
+
+public class MySingleton
+{
+ private theInstance = null;
+
+ private MySingleton() {}
+
+ public MySingleton getInstance() {
+ if ( theInstance == null ) { // synchronize only if necessary
+ synchronized( MySingleton.class ) {
+ if ( s_singleton == null ) {
+ theInstance = new MySingleton();
+ }
+ }
+ }
+ }
+}
+
+
+ The problem with the DCL idiom in Java is that it just does not work correctly.
+ Using it introduces bugs that are extremely hard to track down and reproduce.
+ The
+ "Double-Checked Locking is Broken" Declaration has an in depth explanation
+ of the exact problem which has to do with the semantics of the Java memory model.
+
+ Examples
+
+ To configure the check:
+
+
+<module name="DoubleCheckedLocking"/>
+
+ Package
+
+ com.puppycrawl.tools.checkstyle.checks
+
+ Parent Module
+
+ TreeWalker
+
+
diff --git a/docs/releasenotes.html b/docs/releasenotes.html
index 6a049cd8d..532f111ed 100644
--- a/docs/releasenotes.html
+++ b/docs/releasenotes.html
@@ -76,6 +76,9 @@
[Bloch, Effective Java], Item 17 "Use interfaces only to define
types").
+ Added check to detect the double-checked locking
+ idiom (module DoubleCheckedLocking, request 709333).
+
Added check to enforce C style (char c[]) or Java
style (char[] c) for array type declaration (module ArrayTypeStyle,
request 493380).
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheck.java
new file mode 100644
index 000000000..2050477fd
--- /dev/null
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheck.java
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2002 Oliver Burn
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+package com.puppycrawl.tools.checkstyle.checks;
+
+import antlr.collections.AST;
+import com.puppycrawl.tools.checkstyle.api.Check;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Detect the double-checked locking idiom, a technique that tries to avoid
+ * synchronization overhead but is incorrect because of subtle artifacts of
+ * the java memory model.
+ *
+ * See The "Double-Checked Locking is Broken" Declaration
+ * for a more in depth explanation.
+ *
+ * @author Lars Kühne
+ */
+public class DoubleCheckedLockingCheck extends Check
+{
+ /** @see Check */
+ public int[] getDefaultTokens()
+ {
+ return new int[]{TokenTypes.LITERAL_IF};
+ }
+
+ /** @see Check */
+ public void visitToken(DetailAST aAST)
+ {
+ DetailAST synchronizedAST =
+ getLowestParent(aAST, TokenTypes.LITERAL_SYNCHRONIZED);
+ if (synchronizedAST == null) {
+ return;
+ }
+
+ DetailAST ifAST =
+ getLowestParent(synchronizedAST, TokenTypes.LITERAL_IF);
+ if (ifAST == null) {
+ return;
+ }
+
+ if (getIfCondition(aAST).equalsTree(getIfCondition(ifAST))) {
+ log(aAST.getLineNo(), aAST.getColumnNo(),
+ "doublechecked.locking.avoid");
+ }
+ }
+
+ /**
+ * returns the condition of an if statement.
+ * @param aIfAST the LITERAL_IF AST
+ * @return the AST that represents the condition of the if statement
+ */
+ private AST getIfCondition(DetailAST aIfAST)
+ {
+ return aIfAST.getFirstChild().getNextSibling();
+ }
+
+ /**
+ * searches towards the root of the AST for a specific AST type.
+ * @param aAST the starting node for searching (inclusive)
+ * @param aTokenType the token type to search for
+ * @return the first token of type aTokenTye or null if no such token exists
+ */
+ private DetailAST getLowestParent(DetailAST aAST, int aTokenType)
+ {
+ DetailAST synchronizedParent = aAST;
+ while (synchronizedParent != null
+ && synchronizedParent.getType() != aTokenType)
+ {
+ synchronizedParent = synchronizedParent.getParent();
+ }
+ return synchronizedParent;
+ }
+}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties
index 0d6ce9176..7085fb237 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties
@@ -72,3 +72,5 @@ translation.missingKey=Key ''{0}'' missing.
simplify.expression=Expression can be simplified.
simplify.boolreturn=Conditional logic can be removed.
+
+doublechecked.locking.avoid=The double-checked locking idiom is broken and should be avoided.
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_de.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_de.properties
index 0059dba74..5f4a9f43f 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_de.properties
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_de.properties
@@ -73,3 +73,5 @@ translation.missingKey=
simplify.expression=Der Ausdruck kann vereinfacht werden.
simplify.boolreturn=Die Verzweigung sollte entfernt werden.
+
+doublechecked.locking.avoid=Das ''double-checked locking'' Idiom sollte vermieden werden.
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fi.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fi.properties
index 92acb54bf..9b4910419 100755
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fi.properties
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fi.properties
@@ -72,3 +72,5 @@ translation.missingKey=Käännösavain ''{0}'' puuttuu.
simplify.expression=Ilmaisua voisi yksinkertaistaa.
simplify.boolreturn=Konditionaalilogiikan voisi poistaa.
+
+doublechecked.locking.avoid=The double-checked locking idiom is broken and should be avoided.
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fr.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fr.properties
index 2d2bfec23..255932208 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fr.properties
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_fr.properties
@@ -72,3 +72,5 @@ translation.missingKey=Clef ''{0}'' manquante.
simplify.expression=L'expression peut-être simplifiée.
simplify.boolreturn=Supprimez la logique conditionnelle.
+
+doublechecked.locking.avoid=The double-checked locking idiom is broken and should be avoided.
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_pt.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_pt.properties
index c45e52994..a30c238ef 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_pt.properties
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages_pt.properties
@@ -72,3 +72,5 @@ translation.missingKey=Falta a chave ''{0}''.
simplify.expression=Expressão pode ser simplicada.
simplify.boolreturn=A lógica condicional deve ser removida.
+
+doublechecked.locking.avoid=The double-checked locking idiom is broken and should be avoided.
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java
index 074afc58c..cf09230f4 100644
--- a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java
+++ b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java
@@ -55,6 +55,7 @@ import com.puppycrawl.tools.checkstyle.checks.UpperEllCheckTest;
import com.puppycrawl.tools.checkstyle.checks.VisibilityModifierCheckTest;
import com.puppycrawl.tools.checkstyle.checks.WhitespaceAfterCheckTest;
import com.puppycrawl.tools.checkstyle.checks.WhitespaceAroundTest;
+import com.puppycrawl.tools.checkstyle.checks.DoubleCheckedLockingCheckTest;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -78,6 +79,7 @@ public class AllTests {
suite.addTest(new TestSuite(AvoidStarImportTest.class));
suite.addTest(new TestSuite(ConfigurationLoaderTest.class));
suite.addTest(new TestSuite(ConstantNameCheckTest.class));
+ suite.addTest(new TestSuite(DoubleCheckedLockingCheckTest.class));
suite.addTest(new TestSuite(EmptyBlockCheckTest.class));
suite.addTest(new TestSuite(EmptyForIteratorPadCheckTest.class));
suite.addTest(new TestSuite(EqualsHashCodeCheckTest.class));
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheckTest.java
new file mode 100644
index 000000000..560c240df
--- /dev/null
+++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/DoubleCheckedLockingCheckTest.java
@@ -0,0 +1,22 @@
+package com.puppycrawl.tools.checkstyle.checks;
+
+import com.puppycrawl.tools.checkstyle.BaseCheckTestCase;
+import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
+
+/**
+ * @author lkuehne
+ */
+public class DoubleCheckedLockingCheckTest
+ extends BaseCheckTestCase
+{
+ public void testIt() throws Exception
+ {
+ final DefaultConfiguration checkConfig =
+ createCheckConfig(DoubleCheckedLockingCheck.class);
+ final String[] expected = {
+ "34:17: The double-checked locking idiom is broken and should be avoided.",
+ };
+ verify(checkConfig, getPath("InputDoubleCheckedLocking.java"), expected);
+
+ }
+}