Skip to main content

Lazy Initialization of Static Fields Should Be Synchronized

High
reliabilitymulti-threading

What is it?

In a multi-threaded situation, un-synchronized lazy initialization of static fields could lead to a race condition, where a second thread accesses an incompletely initialized object.

Why apply it?

Accessing an incompletely initialized object can lead to unpredictable behavior and serious bugs in applications, especially in concurrent environments. Synchronization ensures that object initialization is atomic across threads.

How to fix it?

Synchronize the initialization block of lazy static fields to ensure thread safety.

Examples

Example 1:

Negative

This example does not synchronize the method, risking a race condition during initialization.

import java.util.Properties;

public class Config {
private static Properties fSettings = null;

private static Properties getSettings() {
if (fSettings == null) {
fSettings = new Properties(); // Noncompliant
fSettings.put("mode", "safe");
fSettings.put("timeout", "30");
loadSettings();
}
return fSettings;
}

private static void loadSettings() {
// Load additional settings here
}
}

Example 2:

Positive

This example synchronizes the method to ensure thread-safe initialization of the static field.

import java.util.Properties;

public class Config {
private static Properties fSettings = null;

private static synchronized Properties getSettings() {
if (fSettings == null) {
fSettings = new Properties();
fSettings.put("mode", "safe");
fSettings.put("timeout", "30");
loadSettings();
}
return fSettings;
}

private static void loadSettings() {
// Load additional settings here
}
}

Negative

This example is missing the synchronized block, leading to potential concurrent issues during initialization.

import java.util.List;
import java.util.ArrayList;

public class Resources {
private static List<String> resourceNames = null;

private static List<String> getResourceNames() {
if (resourceNames == null) {
resourceNames = new ArrayList<>(); // Noncompliant
loadResources(resourceNames);
}
return resourceNames;
}

private static void loadResources(List<String> resources) {
resources.add("DATABASE");
resources.add("FILE_SYSTEM");
}
}

Example 3:

Positive

This example uses a synchronized block within the method to ensure thread-safe initialization of the static field.

import java.util.List;
import java.util.ArrayList;

public class Resources {
private static List<String> resourceNames = null;

private static List<String> getResourceNames() {
synchronized (Resources.class) {
if (resourceNames == null) {
resourceNames = new ArrayList<>();
loadResources(resourceNames);
}
}
return resourceNames;
}

private static void loadResources(List<String> resources) {
resources.add("DATABASE");
resources.add("FILE_SYSTEM");
}
}