logo

Java Atomic

v Javě, atomové proměnné a operace používá se souběžně. The vícevláknové prostředí vede k problému, kdy konkurence je jednotný. Sdílená entita, jako jsou objekty a proměnné, mohou být změněny během provádění programu. Mohou tedy vést k nekonzistentnosti programu. Je tedy důležité starat se o sdílenou entitu při souběžném přístupu. V takových případech je atomová proměnná může to být řešení. V této části budeme diskutovat atomové třídy, atomové proměnné, atomové operace , spolu s příklady.

numpy směrodatná odchylka

Než budete pokračovat v této části, ujistěte se, že jste si toho vědomi vlákno , synchronizace , a zámek v Javě.

Atomové třídy Java

Jáva poskytuje a java.util.concurrent.atomic balíček, ve kterém jsou definovány atomové třídy. Atomové třídy poskytují a bez zámku a bezpečné pro vlákna prostředí nebo programování na jedné proměnné. Podporuje také atomové operace. Všechny atomické třídy mají metody get() a set(), které pracují s těkavou proměnnou. Metoda funguje stejně jako čtení a zápis na těkavé proměnné.

Balíček poskytuje následující atomové třídy:

Třída Popis
AtomicBoolean Používá se k atomické aktualizaci booleovské hodnoty.
AtomicInteger Používá se k atomické aktualizaci celočíselné hodnoty.
AtomicIntegerArray Pole int, ve kterém mohou být prvky aktualizovány atomicky.
AtomicIntegerFieldUpdater Obslužný program založený na reflexi, který umožňuje atomické aktualizace určených polí volatile int určených tříd.
AtomicLong Používá se k atomické aktualizaci dlouhé hodnoty.
AtomicLongArray Dlouhé pole, ve kterém mohou být prvky aktualizovány atomicky.
AtomicLongFieldUpdater Obslužný program založený na reflexi, který umožňuje atomické aktualizace určených nestálých dlouhých polí určených tříd.
AtomicMarkableReference AtomicMarkableReference udržuje odkaz na objekt spolu s bitem značky, který lze atomicky aktualizovat.
AtomicReference Odkaz na objekt, který může být aktualizován atomicky.
AtomicReferenceArray Pole odkazů na objekty, ve kterých mohou být prvky aktualizovány atomicky.
AtomicReferenceFieldUpdater Obslužný program založený na reflexi, který umožňuje atomické aktualizace určených nestálých referenčních polí určených tříd.
AtomicStampedReference AtomicStampedReference udržuje odkaz na objekt spolu s celočíselným „razítkem“, které lze atomicky aktualizovat.
Dvojitý akumulátor Jedna nebo více proměnných, které společně udržují průběžnou dvojitou hodnotu aktualizovanou pomocí dodané funkce.
DoubleAdder Jedna nebo více proměnných, které společně udržují zpočátku nulový dvojitý součet.
LongAccumulator Jedna nebo více proměnných, které společně udržují průběžnou dlouhou hodnotu aktualizovanou pomocí dodané funkce.
LongAdder Jedna nebo více proměnných, které společně udržují zpočátku nulový dlouhý součet.

Objekty těchto tříd představují atomovou proměnnou int, long, boolean a objekt odkaz respektive. Atomové třídy mají některé běžné metody:

Metody Popis
soubor() Slouží k nastavení hodnoty.
dostat() Slouží k získání aktuální hodnoty.
lazySet() Nakonec se nastaví na danou hodnotu.
CompareAndSet Atomicky nastaví hodnotu na danou aktualizovanou hodnotu, pokud aktuální hodnota == očekávaná hodnota.

Atomové operace

Operace, které se vždy provádějí společně, se nazývají atomové operace nebo atomové působení . Všechny atomické operace se buď efektivně provádějí najednou, nebo se nedějí vůbec. Tři Klíčové pojmy spojené s atomovými akcemi v Javě jsou následující:

1. Atomicita se zabývá tím, jaké akce a soubory mají akce neviditelný Zvažte například následující fragment kódu:

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

Ve výše uvedeném kódu je chování souběžného spouštění increment() a decrement() takové nedefinováno a nepředvídatelné .

2. Viditelnost určuje, kdy může být účinek jednoho vlákna viděl jiným. Zvažte například následující fragment kódu:

pokud rudyardem kipling řádek po řádku vysvětlení
 class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements } 

Ve výše uvedeném kódu je možné, že vlákno T2 se nikdy nezastaví, i když vlákno T1 nastaví hodnotu true. Také ne, že neexistuje žádná synchronizace mezi vlákny.

3. Uspořádání určuje, kdy se akce v jednom vlákně vyskytují mimo pořadí vzhledem k jinému vláknu.

 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; } } 

Pořadí, ve kterém se pole aab objeví ve vláknu T2, se může lišit od pořadí, ve kterém byla nastavena ve vláknu T1.

Pojďme to pochopit na příkladu.

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

Ve výše uvedeném úryvku kódu jsme deklarovali proměnnou typu int počet a uvnitř metody incrementCount() jej přiřadila k 1. V takovém případě se buď vše stane dohromady, nebo se nestane vůbec. Představuje tedy an atomový provoz a operace je známá jako atomicita .

Podívejme se na další fragment kódu.

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

Zdá se, že jde také o atomovou operaci, ale není tomu tak. Jedná se o lineární operaci, která se skládá ze tří operací, tj. čtení, úpravy a zápisu. Může se tedy provádět částečně. Ale pokud používáme výše uvedený kód ve vícevláknovém prostředí, vytváří to problém.

Předpokládejme, že jsme zavolali výše uvedený kód v prostředí s jedním vláknem, aktualizovaná hodnota count bude 2. Pokud zavoláme výše uvedenou metodu dvěma samostatnými vlákny, obě přistupují k proměnné současně a také aktualizují hodnotu počítat současně. Abychom se této situaci vyhnuli, používáme atomový provoz.

kruhové plánování

Java podporuje několik typů atomických akcí, jsou následující:

  • Nestálý proměnné
  • Nízkoúrovňové atomové operace (nebezpečné)
  • Atomové třídy

Podívejme se, jak můžeme vytvořit atomovou operaci.

Atomová proměnná

Atomová proměnná nám umožňuje provádět atomickou operaci s proměnnou. Atomické proměnné minimalizují synchronizaci a pomáhají vyhnout se chybám konzistence paměti. Zajišťuje tedy synchronizaci.

Atomický balíček poskytuje následujících pět atomových proměnných:

  • AtomicInteger
  • AtomicLong
  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLongArray

Potřeba atomové proměnné

Podívejme se na následující kód.

Counter.java

příklad java mapy
 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;>

Výše uvedený program poskytuje očekávaný výstup, pokud je spuštěn v prostředí s jedním vláknem. Vícevláknové prostředí může vést k neočekávanému výstupu. Důvodem je to, že když se dvě nebo více vláken pokouší aktualizovat hodnotu současně, nemusí se správně aktualizovat.

Java nabízí dva řešení k překonání tohoto problému:

  • Pomocí zámku a synchronizace
  • Pomocí atomové proměnné

Vytvořme Java program a pomocí atomové proměnné problém překonáme.

Pomocí atomové proměnné

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;>

Synchronizované vs. Atomový vs. Nestálý

Synchronizováno Atomový Nestálý
Platí pouze pro metody. Platí pouze pro proměnné. Platí také pouze pro proměnné.
Zajišťuje viditelnost spolu s atomicitou. Zajišťuje také viditelnost spolu s atomicitou. Zajišťuje viditelnost, nikoli atomicitu.
Nemůžeme dosáhnout stejného. Nemůžeme dosáhnout stejného. Ukládá se do paměti RAM, takže přístup k nestálým proměnným je rychlý. Neposkytuje však zabezpečení vláken a synchronizaci.
Může být implementován jako synchronizovaný blok nebo synchronizovaná metoda. Nemůžeme dosáhnout stejného. Nemůžeme dosáhnout stejného.
Může zamknout stejný objekt třídy nebo jiný objekt třídy. Nemůžeme dosáhnout stejného. Nemůžeme dosáhnout stejného.