Знакомство с Java Memory Model

МодСль памяти Java (Java Memory Model, JMM) описываСт ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π² срСдС исполнСния Java. МодСль памяти β€” Ρ‡Π°ΡΡ‚ΡŒ сСмантики языка Java, ΠΈ описываСт, Π½Π° Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈ Π½Π° Ρ‡Ρ‚ΠΎ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ€Π°ΡΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ программист, Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ПО Π½Π΅ для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ Java-ΠΌΠ°ΡˆΠΈΠ½Ρ‹, Π° для Java Π² Ρ†Π΅Π»ΠΎΠΌ.

Π˜ΡΡ…ΠΎΠ΄Π½Π°Ρ модСль памяти Java (ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ, Π² частности, относится β€œΠΏΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠΊΠ°Π»ΡŒΠ½Π°Ρ ΠΏΠ°ΠΌΡΡ‚ΡŒβ€), разработанная Π² 1995 Π³ΠΎΠ΄Ρƒ, считаСтся Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠΉ: ΠΌΠ½ΠΎΠ³ΠΈΠ΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ провСсти, Π½Π΅ потСряв Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡŽ бСзопасности ΠΊΠΎΠ΄Π°. Π’ частности, Π΅ΡΡ‚ΡŒ нСсколько Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ β€œΠΎΠ΄ΠΈΠ½ΠΎΡ‡ΠΊΡƒβ€:

  • Π»ΠΈΠ±ΠΎ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π°ΠΊΡ‚ доступа ΠΊ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡ΠΊΠ΅ (Π΄Π°ΠΆΠ΅ ΠΊΠΎΠ³Π΄Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄Π°Π²Π½ΠΎ создан, ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ ΡƒΠΆΠ΅ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒΡΡ) Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΌΠ΅ΠΆΠΏΠΎΡ‚ΠΎΡ‡Π½ΡƒΡŽ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ;
  • Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ стСчСнии ΠΎΠ±ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΡΡ‚Π² систСма выдаст нСдостроСнного ΠΎΠ΄ΠΈΠ½ΠΎΡ‡ΠΊΡƒ;
  • Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ стСчСнии ΠΎΠ±ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΡΡ‚Π² систСма создаст Π΄Π²Π° ΠΎΠ΄ΠΈΠ½ΠΎΡ‡ΠΊΠΈ;
  • Π»ΠΈΠ±ΠΎ конструкция Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π²ΠΈΡΠ΅Ρ‚ΡŒ ΠΎΡ‚ особСнностСй повСдСния Ρ‚ΠΎΠΉ ΠΈΠ»ΠΈ ΠΈΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹.

ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹ памяти Π±Ρ‹Π» ΠΏΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚Π°Π½. Π’ 2005 Π³ΠΎΠ΄Ρƒ, с Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ Java 5 Π±Ρ‹Π» ΠΏΡ€Π΅Π·Π΅Π½Ρ‚ΠΎΠ²Π°Π½ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±Ρ‹Π» Π΅Ρ‰Π΅ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ с Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ Java 14.

Π’ основС Π½ΠΎΠ²ΠΎΠΉ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π»Π΅ΠΆΠ°Ρ‚ Ρ‚Ρ€ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π°:

ΠŸΡ€Π°Π²ΠΈΠ»ΠΎ β„– 1: ΠΎΠ΄Π½ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΡΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΏΡΠ΅Π²Π΄ΠΎΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚: Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ процСссор ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ нСсколько ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π·Π° Ρ‚Π°ΠΊΡ‚, Π·Π°ΠΎΠ΄Π½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ² ΠΈΡ… порядок, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зависимости ΠΏΠΎ Π΄Π°Π½Π½Ρ‹ΠΌ ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ отличаСтся ΠΎΡ‚ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ.

ΠŸΡ€Π°Π²ΠΈΠ»ΠΎ β„– 2: Π½Π΅Ρ‚ Π½Π΅Π²Π΅ΡΡ‚ΡŒ ΠΎΡ‚ΠΊΡƒΠ΄Π° Π²Π·ΡΠ²ΡˆΠΈΡ…ΡΡ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ. Π§Ρ‚Π΅Π½ΠΈΠ΅ любой ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ (ΠΊΡ€ΠΎΠΌΠ΅ Π½Π΅-volatile long ΠΈ double, для ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… это ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ) выдаст Π»ΠΈΠ±ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ (ноль), Π»ΠΈΠ±ΠΎ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ, записанноС Ρ‚ΡƒΠ΄Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ.

И ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ β„– 3: ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ события Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΏΠΎ порядку, Ссли связаны ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ΠΌ строгого частичного порядка β€œΠ²Ρ‹ΠΏΠΎΠ»Π½ΡΠ΅Ρ‚ΡΡ прСТдС” (happens before).

Happens before

ЛСсли Лэмпорт ΠΏΡ€ΠΈΠ΄ΡƒΠΌΠ°Π» понятиС Happens before. Π­Ρ‚ΠΎ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ строгого частичного порядка, Π²Π²Π΅Π΄Π΅Π½Π½ΠΎΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹ΠΌΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ (++ ΠΈ -- Π½Π΅ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹) ΠΈ Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°ΡŽΡ‰Π΅Π΅ β€œΡ„ΠΈΠ·ΠΈΡ‡Π΅ΡΠΊΠΈ прСТдС”.

Оно Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ вторая ΠΊΠΎΠΌΠ°Π½Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ β€œΠ² курсС” ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅Π½Π½Ρ‹Ρ… ΠΏΠ΅Ρ€Π²ΠΎΠΉ.

Happens before

НапримСр, ΠΎΠ΄Π½ΠΎ выполняСтся ΠΏΡ€Π΅ΠΆΠ΄Π΅ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ для Ρ‚Π°ΠΊΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ:

Бинхронизация ΠΈ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Ρ‹:

  • Π—Π°Ρ…Π²Π°Ρ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° (ΠΌΠ΅Ρ‚ΠΎΠ΄ lock, Π½Π°Ρ‡Π°Π»ΠΎ synchronized) ΠΈ всС, Ρ‡Ρ‚ΠΎ происходит Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ΅ послС Π½Π΅Π³ΠΎ.
  • Π’ΠΎΠ·Π²Ρ€Π°Ρ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° (ΠΌΠ΅Ρ‚ΠΎΠ΄ unlock, ΠΊΠΎΠ½Π΅Ρ† synchronized) ΠΈ всС, Ρ‡Ρ‚ΠΎ происходит Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ΅ ΠΏΠ΅Ρ€Π΅Π΄ Π½ΠΈΠΌ.
  • Π’ΠΎΠ·Π²Ρ€Π°Ρ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π·Π°Ρ…Π²Π°Ρ‚ Π΄Ρ€ΡƒΠ³ΠΈΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ.

Π—Π°ΠΏΠΈΡΡŒ ΠΈ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅:

  • Π—Π°ΠΏΠΈΡΡŒ Π² Π»ΡŽΠ±ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ Π΅Π΅ ΠΆΠ΅ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.
  • ВсС, Ρ‡Ρ‚ΠΎ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ΅ ΠΏΠ΅Ρ€Π΅Π΄ записью Π² volatile-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ, ΠΈ сама запись. volatile-Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈ всС, Ρ‡Ρ‚ΠΎ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ΅ послС Π½Π΅Π³ΠΎ.
  • Π—Π°ΠΏΠΈΡΡŒ Π² volatile-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ считываниС Π΅Π΅ ΠΆΠ΅. Volatile-запись взаимодСйствуСт с ΠΏΠ°ΠΌΡΡ‚ΡŒΡŽ Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΊΠ°ΠΊ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π°, Π° Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊ Π·Π°Ρ…Π²Π°Ρ‚. ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ Ссли ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡ‚ΠΎΠΊ записал Π² volatile-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ» это, всС, Ρ‡Ρ‚ΠΎ ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΠ΅Ρ‚ записи, выполняСтся Ρ€Π°Π½ΡŒΡˆΠ΅ всСго, Ρ‡Ρ‚ΠΎ ΠΈΠ΄Π΅Ρ‚ послС чтСния; смотри рисунок.

ΠžΠ±ΡΠ»ΡƒΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°:

  • БтатичСская инициализация ΠΈ Π»ΡŽΠ±Ρ‹Π΅ дСйствия с Π»ΡŽΠ±Ρ‹ΠΌΠΈ экзСмплярами ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ².
  • Π—Π°ΠΏΠΈΡΡŒ Π² final-поля Π² конструкторС ΠΈ всС, Ρ‡Ρ‚ΠΎ послС конструктора. Как ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ – ΡΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ happens-before Π½Π΅ соСдиняСтся Ρ‚Ρ€Π°Π½Π·ΠΈΡ‚ΠΈΠ²Π½ΠΎ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌΠΈ ΠΈ поэтому ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΌΠ΅ΠΆΠΏΠΎΡ‚ΠΎΡ‡Π½ΡƒΡŽ Π³ΠΎΠ½ΠΊΡƒ.
  • Π›ΡŽΠ±Π°Ρ Ρ€Π°Π±ΠΎΡ‚Π° с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ ΠΈ finalize().

ΠžΠ±ΡΠ»ΡƒΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°:

  • Запуск ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ любой ΠΊΠΎΠ΄ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅.
  • Π—Π°Π½ΡƒΠ»Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, относящихся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ, ΠΈ любой ΠΊΠΎΠ΄ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅.
  • Код Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ ΠΈ join(); ΠΊΠΎΠ΄ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ ΠΈ isAlive() == false.
  • interrupt() ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ Ρ„Π°ΠΊΡ‚Π° остановки.

ΠΡŽΠ°Π½ΡΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Happens before

ОсвобоТдСниС (releasing) ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° happens-before происходит ΠΏΡ€Π΅ΠΆΠ΄Π΅, Ρ‡Π΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ (acquiring) Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π°. Π‘Ρ‚ΠΎΠΈΡ‚ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΈΠΌΠ΅Π½Π½ΠΎ освобоТдСниС, Π° Π½Π΅ Π²Ρ‹Ρ…ΠΎΠ΄, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π·Π° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ использовании wait ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡ‚ΡŒΡΡ.

Рассмотрим, ΠΊΠ°ΠΊ это Π·Π½Π°Π½ΠΈΠ΅ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°ΠΌ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ наш ΠΏΡ€ΠΈΠΌΠ΅Ρ€. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС всС ΠΎΡ‡Π΅Π½ΡŒ просто: достаточно ΡƒΠ±Ρ€Π°Ρ‚ΡŒ внСшнюю ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ ΠΈ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΊΠ°ΠΊ Π΅ΡΡ‚ΡŒ. Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚ всС измСнСния, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠ½ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π΅Π³ΠΎ отпустит. А Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ Π΅Π³ΠΎ Π½Π΅ отпустит, ΠΏΠΎΠΊΠ° всС Π½Π΅ ΠΏΡ€ΠΎΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚, ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄Π΅ΠΌ всС измСнСния сразу, Π° Π½Π΅ ΠΏΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ:

public class Keeper {
    private Data data = null;

    public Data getData() {
        synchronized(this) {
            if(data == null) {
                data = new Data();
            }
        }

        return data;
    }
}

Π—Π°ΠΏΠΈΡΡŒ Π² volatile ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ happens-before Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈΠ· Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Π’ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΡ‹ внСсли, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, исправляСт Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ, Π½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚ΠΎΠ³ΠΎ, ΠΊΡ‚ΠΎ написал ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄, Ρ‚ΡƒΠ΄Π°, ΠΎΡ‚ΠΊΡƒΠ΄Π° ΠΎΠ½ ΠΏΡ€ΠΈΡˆΠ΅Π» β€” ΠΊ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·. Бпасти ΠΌΠΎΠΆΠ΅Ρ‚ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово volatile. ЀактичСски, рассматриваСмоС ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Ρ‡Ρ‚Π΅Π½ΠΈΠΈ всСго, Ρ‡Ρ‚ΠΎ объявлСно volatile, ΠΌΡ‹ всСгда Π±ΡƒΠ΄Π΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ я Π³ΠΎΠ²ΠΎΡ€ΠΈΠ» Ρ€Π°Π½ΡŒΡˆΠ΅, для volatile ΠΏΠΎΠ»Π΅ΠΉ запись всСгда (Π² Ρ‚ΠΎΠΌ числС long ΠΈ double) являСтся Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ. Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚: Ссли Ρƒ вас Π΅ΡΡ‚ΡŒ volatile ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ, ΠΈΠΌΠ΅ΡŽΡ‰Π°Ρ ссылки Π½Π° Π΄Ρ€ΡƒΠ³ΠΈΠ΅ сущности (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, массив, List ΠΈΠ»ΠΈ ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π΅Ρ‰Π΅ класс), Ρ‚ΠΎ всСгда β€œΡΠ²Π΅ΠΆΠ΅ΠΉβ€ Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ссылка Π½Π° саму ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ, Π½ΠΎ Π½Π΅ Π½Π° всС, Π² Π½Π΅Π΅ входящСС.

Π˜Ρ‚Π°ΠΊ, ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊ нашим Double-locking Π±Π°Ρ€Π°Π½Π°ΠΌ. Π‘ использованиСм volatile ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ Ρ‚Π°ΠΊ:

public class Keeper {
    private volatile Data data = null;

    public Data getData() {
        if(data == null) {
            synchronized(this) {
                if(data == null) {
                    data = new Data();
                }
            }
        }
        return data;
    }
}

Π’ΡƒΡ‚ Ρƒ нас ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ Π΅ΡΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°, Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² случаС, Ссли data == null. ΠžΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ случаи ΠΌΡ‹ отсСиваСм, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ volatile read. ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ обСспСчиваСтся Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ volatile store happens-before volatile read, ΠΈ всС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ происходят Π² конструкторС, Π²ΠΈΠ΄Π½Ρ‹ Ρ‚ΠΎΠΌΡƒ, ΠΊΡ‚ΠΎ Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ поля.