I have this class
public class Singletons {
private static UserService userService;
private static OrderService orderService;
public static UserService getUserService() {
if (userService == null) {
synchronized (Singletons.class) {
if (userService == null)
userService = new UserService();
}
}
return userService;
}
public static OrderService getOrderService() {
if (orderService == null) {
synchronized (Singletons.class) {
if (orderService == null)
orderService = new OrderService();
}
}
return orderService;
}
}
Intellij IDEA shows me this warrnig:
Double-checked locking tries to initialize a field on demand and in a thread-safe manner while avoiding the cost of synchronization. Unfortunately it is not thread-safe when used on a field that is not declared volatile. When using Java 1.4 or earlier, double-checked locking doesn't work even with volatile fields. Read the article linked above for the detailed explanation of the problem.
And this link: The "Double-Checked Locking is Broken" Declaration
I read this article but I can not understand how I can fix my class. As I understood I can do the following:
public class Singletons {
private static volatile UserService userService;
private static volatile OrderService orderService;
public static UserService getUserService() {
if (userService == null) {
synchronized (Singletons.class) {
if (userService == null)
userService = new UserService();
}
}
return userService;
}
public static OrderService getOrderService() {
if (orderService == null) {
synchronized (Singletons.class) {
if (orderService == null)
orderService = new OrderService();
}
}
return orderService;
}
}
Is this enough?(EDDIT - I use java > 1.4 so it is not for me) Or the second approach might be like this:
public class Singletons {
private static final UserService userService = new UserService();
private static final OrderService orderService = new OrderService();
public static UserService getUserService() {
return userService;
}
public static OrderService getOrderService() {
return orderService;
}
}
But it looks strange. What if I need to pass other classes to the constructor? It looks wrong. Maybe this, like in this answer(StackOverflow answer):
public class Singletons {
private static class Ref {
static final UserService userService = new UserService();
static final OrderService orderService = new OrderService();
}
public static UserService getUserService() {
return Ref.userService;
}
public static OrderService getOrderService() {
return Ref.orderService;
}
}
But it looks the same as the previous one. So How can I create the correct lazy singleton?