В 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 хиляди.
Но в случая с многопоточност, дори ако цялочисловата променлива е атомарна, може да има проблеми със сигурността на нишките, което е проблем с видимостта на нишките, затова трябва да добавите волатилно твърдение.
Този модификатор е принудителна променлива, която се чете от паметта всеки път и не се съхранява в регистри. |