logo

Java Atomic

В Java, атомни променливи и операции използвани в паралелност. The многопоточност среда води до проблем, когато едновременност е унифицирана. Споделеният обект като обекти и променливи може да бъде променен по време на изпълнението на програмата. Следователно те могат да доведат до несъответствие на програмата. Така че е важно да се грижите за споделения обект, докато осъществявате достъп едновременно. В такива случаи, атомна променлива може да бъде решение за него. В този раздел ще обсъдим атомарни класове, атомарни променливи, атомарни операции , заедно с примери.

сортиране на черупки

Преди да продължите напред в този раздел, уверете се, че сте запознати с резба , синхронизация , и ключалка в Java.

Атомни класове на Java

Java осигурява a java.util.concurrent.atomic пакет, в който са дефинирани атомни класове. Атомните класове осигуряват a без заключване и безопасен за нишки среда или програмиране върху една променлива. Той също така поддържа атомни операции. Всички атомарни класове имат методите get() и set(), които работят върху променливата volatile. Методът работи по същия начин като четене и запис върху летливи променливи.

Пакетът предоставя следните атомни класове:

Клас Описание
AtomicBoolean Използва се за атомарно актуализиране на булева стойност.
Атомно цяло число Използва се за актуализиране на целочислена стойност атомарно.
AtomicIntegerArray Int масив, в който елементите могат да се актуализират атомарно.
AtomicIntegerFieldUpdater Помощна програма, базирана на отражение, която позволява атомарни актуализации на определени летливи int полета на определени класове.
AtomicLong Използва се за атомарно актуализиране на дълга стойност.
AtomicLongArray Дълъг масив, в който елементите могат да се актуализират атомарно.
AtomicLongFieldUpdater Помощна програма, базирана на отражение, която позволява атомарни актуализации на определени летливи дълги полета на определени класове.
AtomicMarkableReference AtomicMarkableReference поддържа препратка към обект заедно с бит за маркиране, който може да се актуализира атомарно.
AtomicReference Препратка към обект, която може да се актуализира атомарно.
AtomicReferenceArray Масив от препратки към обекти, в които елементите могат да се актуализират атомарно.
AtomicReferenceFieldUpdater Помощна програма, базирана на отражение, която позволява атомарни актуализации на определени променливи референтни полета на определени класове.
AtomicStampedReference AtomicStampedReference поддържа препратка към обект заедно с целочислен 'печат', който може да се актуализира атомарно.
DoubleAccumulator Една или повече променливи, които заедно поддържат работеща двойна стойност, актуализирана с помощта на предоставена функция.
DoubleAdder Една или повече променливи, които заедно поддържат първоначално нулева двойна сума.
LongAccumulator Една или повече променливи, които заедно поддържат текуща дълга стойност, актуализирана с помощта на предоставена функция.
LongAdder Една или повече променливи, които заедно поддържат първоначално нулева дълга сума.

Обектите от тези класове представляват атомната променлива на int, long, boolean , и обект справка съответно. Атомните класове имат някои общи методи, както следва:

Методи Описание
комплект() Използва се за задаване на стойността.
получи() Използва се за получаване на текущата стойност.
lazySet() В крайна сметка се задава зададената стойност.
compareAndSet Атомично задава стойността на дадената актуализирана стойност, ако текущата стойност == очакваната стойност.

Атомни операции

Тези операции, които винаги се изпълняват заедно, са известни като атомни операции или атомно действие . Всички атомарни операции или се изпълняват ефективно се случват наведнъж или не се случват изобщо. Три ключовите концепции, свързани с атомарните действия в Java, са както следва:

1. Атомичността се занимава с това кои действия и набори от действия имат невидим Например, разгледайте следния кодов фрагмент:

 class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement } 

В горния код поведението при едновременно изпълнение на increment() и decrement() е недефиниран и не е предвидимо .

2. Видимостта определя кога може да бъде ефектът от една нишка видяно от друг. Например, разгледайте следния кодов фрагмент:

 class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements } 

В горния код е възможно нишка T2 никога да не спре дори след като нишка T1 зададе done на true. Освен това не че няма синхронизация между нишките.

3. Подреждането определя кога действията в една нишка се случват извън ред по отношение на друга нишка.

 class Order { boolean a=false; boolean b=false; void demo1() //thread T1 { a=true; b=true; } boolean demo2() //thread T2 { boolean r1=b; //sees true boolean r2=a; //sees false boolean r3=a; //sees true //returns true return (r1 && !r2) && r3; } } 

Редът, в който се появяват полета a и b в нишка T2, може да се различава от реда, в който са зададени в нишка T1.

fizzbuzz java

Нека го разберем чрез пример.

 public class AtomicExample { int count; public void incrementCount() { count=1; } 

В горния кодов фрагмент сме декларирали променлива тип int броя и вътре в метода incrementCount() го присвои на 1. В такъв случай или всички се случват заедно, или няма да се случи изобщо. Следователно, той представлява атомна операция и операцията е известна като атомарност .

Нека разгледаме друг кодов фрагмент.

 public class AtomicExample { int count; public void incrementCount() { count=count+1; } 

Изглежда, че това също е атомна операция, но не е така. Това е линейна операция, която се състои от три операции, т.е. четене, модифициране и запис. Следователно може да се изпълни частично. Но ако използваме горния код в многонишкова среда, това създава проблем.

Да предположим, че сме извикали горния код в среда с една нишка, актуализираната стойност на count ще бъде 2. Ако извикаме горния метод от две отделни нишки, и двете имат достъп до променливата едновременно и също така актуализират стойността на броят едновременно. За да избегнем тази ситуация, използваме атомарна операция.

какво е hashset java

Java поддържа няколко типа атомарни действия, както следва:

  • Летлив променливи
  • Атомни операции на ниско ниво (опасни)
  • Атомни класове

Нека да видим как можем да създадем атомарна операция.

Атомна променлива

Атомната променлива ни позволява да извършим атомарна операция върху променлива. Атомарните променливи минимизират синхронизацията и помагат да се избегнат грешки в последователността на паметта. Следователно, той осигурява синхронизация.

Атомният пакет предоставя следните пет атомни променливи:

  • Атомно цяло число
  • AtomicLong
  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLongArray

Необходимостта от атомна променлива

Нека разгледаме следния код.

преминаване на двоично дърво по пощата

Counter.java

 class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, 'first'); t2="new" 'second'); t3="new" 'third'); t4="new" 'fourth'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <p>The above program gives the expected output if it is executed in a single-threaded environment. A multi-threaded environment may lead to unexpected output. The reason behind it that when two or more threads try to update the value at the same time then it may not update properly.</p> <p>Java offers <strong>two</strong> solutions to overcome this problem:</p> <ul> <li>By using lock and synchronization</li> <li>By using atomic variable</li> </ul> <p>Let&apos;s create a Java program and use an atomic variable to overcome the problem.</p> <h3>By using Atomic Variable</h3> <p> <strong>AtomicExample.java</strong> </p> <pre> class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, 'first'); t2="new" 'second'); t3="new" 'third'); t4="new" 'fourth'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <h2>Synchronized Vs. Atomic Vs. Volatile</h2> <table class="table"> <tr> <th>Synchronized</th> <th>Atomic</th> <th>Volatile</th> </tr> <tr> <td>It applies to methods only.</td> <td>It applies to variables only.</td> <td>It also applies to variables only.</td> </tr> <tr> <td>It ensures visibility along with atomicity.</td> <td>It also ensures visibility along with atomicity.</td> <td>It ensures visibility, not atomicity.</td> </tr> <tr> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> <td>It stores in RAM, so accessing volatile variables is fast. But it does not provide thread-safety and synchronization.</td> </tr> <tr> <td>It can be implemented as a synchronized block or a synchronized method.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> </table> <hr></max;></pre></max;>

Горната програма дава очаквания резултат, ако се изпълнява в еднонишкова среда. Многонишкова среда може да доведе до неочакван резултат. Причината зад това е, че когато две или повече нишки се опитат да актуализират стойността едновременно, тогава тя може да не се актуализира правилно.

Java предлага две решения за преодоляване на този проблем:

  • Чрез използване на заключване и синхронизация
  • Чрез използване на атомна променлива

Нека създадем Java програма и използваме атомарна променлива, за да преодолеем проблема.

Чрез използване на атомна променлива

AtomicExample.java

 class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, \'first\'); t2="new" \'second\'); t3="new" \'third\'); t4="new" \'fourth\'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <h2>Synchronized Vs. Atomic Vs. Volatile</h2> <table class="table"> <tr> <th>Synchronized</th> <th>Atomic</th> <th>Volatile</th> </tr> <tr> <td>It applies to methods only.</td> <td>It applies to variables only.</td> <td>It also applies to variables only.</td> </tr> <tr> <td>It ensures visibility along with atomicity.</td> <td>It also ensures visibility along with atomicity.</td> <td>It ensures visibility, not atomicity.</td> </tr> <tr> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> <td>It stores in RAM, so accessing volatile variables is fast. But it does not provide thread-safety and synchronization.</td> </tr> <tr> <td>It can be implemented as a synchronized block or a synchronized method.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> </table> <hr></max;>

Синхронизирано срещу. Atomic Vs. Летлив

Синхронизирано Атомен Летлив
Отнася се само за методите. Прилага се само за променливи. Прилага се и само за променливи.
Осигурява видимост заедно с атомарност. Той също така осигурява видимост заедно с атомарността. Осигурява видимост, а не атомарност.
Ние не можем да постигнем същото. Ние не можем да постигнем същото. Съхранява се в RAM, така че достъпът до летливи променливи е бърз. Но не осигурява безопасност на нишката и синхронизация.
Може да се реализира като синхронизиран блок или синхронизиран метод. Ние не можем да постигнем същото. Ние не можем да постигнем същото.
Може да заключва същия обект на клас или различен обект на клас. Ние не можем да постигнем същото. Ние не можем да постигнем същото.