22
33public final class Singleton {
44 // EN: The field must be declared volatile so that double check lock would
5- // work.
6- //
7- // See: https://refactoring.guru/java-dcl-issue
5+ // work correctly.
86 //
97 // RU: Поле обязательно должно быть объявлено volatile, чтобы двойная
108 // проверка блокировки сработала как надо.
11- //
12- // См: https://refactoring.guru/java-dcl-issue
139 private static volatile Singleton instance ;
1410
1511 public String value ;
@@ -19,32 +15,34 @@ private Singleton(String value) {
1915 }
2016
2117 public static Singleton getInstance (String value ) {
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.
18+ // EN: The approach taken here is called double-checked locking (DCL).
19+ // It exists to prevent race condition between multiple threads that may
20+ // attempt to get singleton instance at the same time, creating
21+ // separate instances as a result.
22+ //
23+ // It may seem that having the `result` variable here is completely
24+ // pointless. There is, however, a very important caveat when
25+ // implementing double-checked locking in Java, which is solved by
26+ // introducing this local variable.
27+ //
28+ // You can read more info DCL issues in Java here:
29+ // https://refactoring.guru/java-dcl-issue
2530 //
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.
31+ // RU: Тезника, которую мы здесь применяем называется «блокировка с
32+ // двойной проверкой» (Double-Checked Locking). Она применяется, чтобы
33+ // предотвратить создание нескольких объектов-одиночек, если метод будет
34+ // вызван из нескольких потоков одновременно.
3335 //
34- // RU: Вам может быть неясно зачем мы используем дублирующую локальную
35- // переменную здесь. Это — микрооптимизация .
36+ // Хотя переменная `result` вполне оправданно кажется здесь лишней, она
37+ // помогает избежать подводных камней реализации DCL в Java .
3638 //
37- // Поле одиночки объявлено как volatile, что заставляет программу
38- // обновлять её значение из памяти каждый раз при доступе к переменной,
39- // тогда как значение обычной переменной может быть записано в регистр
40- // процессора для более быстрого чтения. Используя дополнительную
41- // локальную перменную, мы можем ускорить работу с переменной, обновляя
42- // значение поля только тогда, когда действительно нужно.
39+ // Больше об этой проблеме можно почитать здесь:
40+ // https://refactoring.guru/ru/java-dcl-issue
4341 Singleton result = instance ;
4442 if (result != null ) {
4543 return result ;
4644 }
47- synchronized (this ) {
45+ synchronized (Singleton . class ) {
4846 if (instance == null ) {
4947 instance = new Singleton (value );
5048 }
0 commit comments