„Здрасти, Амиго!“
„Здравей, Ели!“
„Искам да ви разкажа за летливия модификатор. Знаете ли Howво е това?“
— Нещо свързано с конци. Не помня точно.
„Тогава слушайте. Ето някои технически подробности за вас:“
„Един компютър има два вида памет: глобална (обикновена) памет и памет, вградена в процесора. Вградената памет на процесора е разделена на регистри, кеш от първо ниво (L1), кеш от второ ниво (L2) и трето ниво (L3)."
"Тези типове памет имат различни скорости. Най-бързата и най-малката памет са регистрите, след това кеша на процесора (L1, L2, L3) и накрая глобалната памет (най-бавната)."
„Глобалната памет и кешът на процесора работят с много различни скорости, така че Java машината позволява на всяка нишка да съхранява най-често използваните променливи в паметта на локалната нишка (в кеша на процесора).“
„Може ли този процес по няHowъв начин да бъде контролиран?“
„Не съвсем. Цялата работа се извършва от Java машината. Тя е много интелигентна, когато става въпрос за оптимизиране на производителността.“
„Но ето защо ви казвам това. Има един малък проблем. Когато две нишки работят с една и съща променлива, всяка може да съхранява копие в собствения си локален кеш. И тогава една нишка може да промени променливата, но втората може да не види промяната, защото все още работи със собствено копие на променливата."
— Е, Howво може да се направи тогава?
„Създателите на Java предоставиха специална ключова дума за тази ситуация: volatile. Ако дадена променлива е достъпна от различни нишки, трябва да я маркирате с модификатора volatile, така че Java машината да не я поставя в кеша. Ето How обикновено изглежда:"
public volatile int count = 0;
„О, спомням си. Вече споменахте това. Вече знам това.“
— Разбира се, че го правиш. Но си го спомни едва когато ти казах.
— Ъ-ъ, добре, малко съм позабравил.
"Повторението е майка на ученето!"
„Ето няколко нови факта за модификатора volatile. Модификаторът volatile гарантира само, че променливата ще бъде прочетена и записана безопасно. Не гарантира, че тя ще бъде променена безопасно.“
"Каква е разликата?"
„Вижте How се променя променливата:“
Код | Какво наистина се случва: | Описание |
---|---|---|
|
|
Стъпка 1. Стойността на променливата count се копира от глобалната памет в регистър на процесора. Стъпка 2. Стъпка 3. |
"Уау! Значи всички променливи се променят само в процесора?"
— Да.
"И стойностите се копират напред и назад: от паметта към процесора и обратно?"
— Да.
„Нестабилният модификатор гарантира, че когато се осъществи достъп до променливата count, тя ще бъде прочетена от паметта (стъпка 1). И ако дадена нишка иска да присвои нова стойност, тя определено ще бъде в глобалната памет (стъпка 3).“
„Но Java машината не гарантира, че няма да има превключване на нишки между стъпки 1 и 3.“
„Така че увеличаването на променливата с 1 всъщност е три операции?“
— Да.
"И ако две нишки едновременно искат да изпълнят count++, тогава те биха могли да си пречат?"
„Да, вижте го:“
Тема 1 | Нишка 2 | Резултат |
---|---|---|
|
|
|
„И така, можете да получите достъп до променливата, но промяната й все още е рисковано?“
„Е, можеш да го промениш, само внимавай ☺“
"Как?"
" Синхронизираният е нашият най-добър приятел."
"Виждам."
GO TO FULL VERSION