|
1 | 1 | package refactoring_guru.singleton.example.thread_safe; |
2 | 2 |
|
3 | 3 | public final class Singleton { |
| 4 | + // EN: The field must be declared volatile so that double check lock would |
| 5 | + // work. |
| 6 | + // |
| 7 | + // See: https://refactoring.guru/java-dcl-issue |
| 8 | + // |
| 9 | + // RU: Поле обязательно должно быть объявлено volatile, чтобы двойная |
| 10 | + // проверка блокировки сработала как надо. |
| 11 | + // |
| 12 | + // См: https://refactoring.guru/java-dcl-issue |
4 | 13 | private static volatile Singleton instance; |
| 14 | + |
5 | 15 | public String value; |
6 | 16 |
|
7 | 17 | private Singleton(String value) { |
8 | 18 | this.value = value; |
9 | 19 | } |
10 | 20 |
|
11 | 21 | public static Singleton getInstance(String value) { |
12 | | - if (instance == null) { |
| 22 | + // EN: This code may appear a bit convoluted. In particular, the need |
| 23 | + // for the local variable result may be unclear. This is a micro- |
| 24 | + // optimization. |
| 25 | + // |
| 26 | + // The field would be read first time in the first if statement and |
| 27 | + // second time in the return statement. The field is declared volatile, |
| 28 | + // which means it has to be refetched from memory every time it is |
| 29 | + // accessed (more processing is required to access volatile variables) |
| 30 | + // and can not be stored into a register by the compiler. When copied to |
| 31 | + // the local variable and then used in both statements (if and return), |
| 32 | + // the register optimization can be done by the JVM. |
| 33 | + // |
| 34 | + // RU: Вам может быть неясно зачем мы используем дублирующую локальную |
| 35 | + // переменную здесь. Это — микрооптимизация. |
| 36 | + // |
| 37 | + // Поле одиночки объявлено как volatile, что заставляет программу |
| 38 | + // обновлять её значение из памяти каждый раз при доступе к переменной, |
| 39 | + // тогда как значение обычной перменной может быть записано в регистр |
| 40 | + // процессора для более быстрого чтения. Используя дополнительную |
| 41 | + // локальную перменную, мы можем ускорить работу с переменной, обновляя |
| 42 | + // значение поля только тогда, когда действительно нужно. |
| 43 | + Singleton result = instance; |
| 44 | + if (result == null) { |
13 | 45 | synchronized (Singleton.class) { |
14 | | - if (instance == null) { |
15 | | - instance = new Singleton(value); |
| 46 | + result = instance; |
| 47 | + if (result == null) { |
| 48 | + instance = result = new Singleton(value); |
16 | 49 | } |
17 | 50 | } |
18 | 51 | } |
|
0 commit comments