У Java інші базові змінні є атомарними, за винятком 8-байтових, 64-бітних змінних Long і Double.
Модель зберігання Java вимагає, щоб операції отримання та збереження були атомарними, але для енергонезалежних довгих і подвійних змінних JVM дозволяє розділяти 64-бітне читання або запис на дві 32-бітні операції.
Якщо читання і запис відбуваються на різних потоках, читання довгого типу енергонезалежного типу може призвести до високих 32 бітів одного значення і низьких 32 бітів іншого.
Тож навіть якщо вас не цікавлять прострочені дані, може бути небезпечно використовувати спільні, змінювані довгі та подвійні змінні в багатопотоковій програмі, якщо вони не оголошені волатильними або захищені блокуванням.
Говорячи про атомарні операції, це означає, що читання і запис є атомарними, наприклад i=5; Це атомна операція.
Однак, якщо операція двох атомів виконується разом, вона не обов'язково атомарна, наприклад, спочатку читання, а потім запис, то можливо, що змінна була змінена після читання.
i++ — це така операція, спочатку читаєш, а потім записуєш, тобто цілочисельна змінна атомарна, а не те, що i++ є атомарною.
Коли ви використовуєте for(int i=0; i<10000; i++){System.out.print(i)}
Ви побачите, що я не надрукую 10 000, а надрукую близько 8-9 тисяч.
Але у випадку багатопотоковості, навіть якщо цілочисельна змінна атомарна, можуть виникати проблеми з безпекою потоків, що є проблемою видимості потоків, тому потрібно додати оператор з волатильністю.
Цей модифікатор є примусовою змінною, яка щоразу зчитується з пам'яті і не зберігається в регістрах. |