v Jave atómové premenné a operácií používané v súbehu. The viacvláknové prostredia vedie k problému, keď súbežnosť je jednotný. Zdieľanú entitu, ako sú objekty a premenné, možno počas vykonávania programu zmeniť. Môžu teda viesť k nekonzistentnosti programu. Preto je dôležité starať sa o zdieľanú entitu pri súbežnom prístupe. V takýchto prípadoch, atómová premenná môže byť riešením. V tejto časti budeme diskutovať atómové triedy, atómové premenné, atómové operácie , spolu s príkladmi.
škrupinové triedenie
Predtým, ako budete pokračovať v tejto časti, uistite sa, že ste si toho vedomí niť , synchronizácia , a zámok v Jave.
Atómové triedy Java
Java poskytuje a java.util.concurrent.atomic balík, v ktorom sú definované atómové triedy. Atómové triedy poskytujú a bez zámku a bezpečné pre vlákna prostredia alebo programovania na jednej premennej. Podporuje tiež atómové operácie. Všetky atómové triedy majú metódy get() a set(), ktoré pracujú s nestálou premennou. Metóda funguje rovnako ako čítanie a zápis na prchavé premenné.
Balík poskytuje nasledujúce atómové triedy:
Trieda | Popis |
---|---|
AtomicBoolean | Používa sa na atomickú aktualizáciu boolovskej hodnoty. |
AtomicInteger | Používa sa na atomickú aktualizáciu celočíselnej hodnoty. |
AtomicIntegerArray | Pole int, v ktorom sa prvky môžu aktualizovať atomicky. |
AtomicIntegerFieldUpdater | Pomôcka založená na reflexii, ktorá umožňuje atomické aktualizácie určených polí volatile int určených tried. |
AtomicLong | Používa sa na atomickú aktualizáciu dlhej hodnoty. |
AtomicLongArray | Dlhé pole, v ktorom sa prvky môžu aktualizovať atomicky. |
AtomicLongFieldUpdater | Pomôcka založená na reflexii, ktorá umožňuje atomické aktualizácie určených nestálych dlhých polí určených tried. |
AtomicMarkableReference | AtomicMarkableReference udržiava referenciu na objekt spolu s bitom značky, ktorý je možné aktualizovať atomicky. |
AtomicReference | Odkaz na objekt, ktorý možno aktualizovať atomicky. |
AtomicReferenceArray | Pole referencií na objekty, v ktorých môžu byť prvky aktualizované atomicky. |
AtomicReferenceFieldUpdater | Pomôcka založená na reflexii, ktorá umožňuje atomické aktualizácie určených nestálych referenčných polí určených tried. |
AtomicStampedReference | AtomicStampedReference udržiava referenciu na objekt spolu s celočíselnou „pečiatkou“, ktorú možno aktualizovať atomicky. |
Dvojitý akumulátor | Jedna alebo viac premenných, ktoré spolu udržujú priebežnú dvojitú hodnotu aktualizovanú pomocou dodanej funkcie. |
DoubleAdder | Jedna alebo viac premenných, ktoré spolu udržiavajú pôvodne nulový dvojitý súčet. |
LongAkumulátor | Jedna alebo viac premenných, ktoré spolu udržujú priebežnú dlhú hodnotu aktualizovanú pomocou dodanej funkcie. |
LongAdder | Jedna alebo viac premenných, ktoré spolu udržiavajú pôvodne nulový dlhý súčet. |
Objekty týchto tried predstavujú atómovú premennú int, long, boolean a objekt odkaz resp. Atómové triedy majú niektoré bežné metódy, ako sú:
Metódy | Popis |
---|---|
set() | Používa sa na nastavenie hodnoty. |
dostať () | Používa sa na získanie aktuálnej hodnoty. |
lazySet() | Nakoniec sa nastaví na danú hodnotu. |
CompareAndSet | Atomicky nastaví hodnotu na danú aktualizovanú hodnotu, ak aktuálna hodnota == očakávaná hodnota. |
Atómové operácie
Operácie, ktoré sa vždy vykonávajú spoločne, sú známe ako atómové operácie alebo atómová akcia . Všetky atómové operácie sa buď efektívne vykonajú naraz, alebo sa nestanú vôbec. Tri kľúčové pojmy spojené s atómovými akciami v Jave sú nasledovné:
1. Atomicita sa zaoberá tým, aké akcie a súbory majú akcie neviditeľný Zvážte napríklad nasledujúci útržok kódu:
class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement }
Vo vyššie uvedenom kóde je správanie súbežného spustenia increment() a decrement() také isté nedefinované a nepredvídateľné .
2. Viditeľnosť určuje, kedy môže byť efekt jedného vlákna videný iným. Zvážte napríklad nasledujúci útržok kódu:
class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements }
Vo vyššie uvedenom kóde je možné, že vlákno T2 sa nikdy nezastaví, aj keď sa vlákno T1 nastaví na hodnotu true. Tiež nie, že neexistuje synchronizácia medzi vláknami.
3. Usporiadanie určuje, kedy sa akcie v jednom vlákne vyskytnú mimo poradia vzhľadom na iné vlákno.
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; } }
Poradie, v ktorom sa polia a a b zobrazujú vo vlákne T2, sa môže líšiť od poradia, v ktorom boli nastavené vo vlákne T1.
príkaz arp
Poďme to pochopiť na príklade.
public class AtomicExample { int count; public void incrementCount() { count=1; }
Vo vyššie uvedenom úryvku kódu sme deklarovali premennú typu int počítať a vo vnútri metódy incrementCount() ho priradila k 1. V takom prípade sa buď všetko stane spolu, alebo sa nestane vôbec. Preto predstavuje an atómová operácia a operácia je známa ako atomicita .
Pozrime sa na ďalší útržok kódu.
public class AtomicExample { int count; public void incrementCount() { count=count+1; }
Zdá sa, že je to tiež atómová operácia, ale nie je to tak. Ide o lineárnu operáciu, ktorá pozostáva z troch operácií, t. j. čítania, úpravy a zápisu. Preto sa môže vykonať čiastočne. Ale ak používame vyššie uvedený kód vo viacvláknovom prostredí, vytvára to problém.
Predpokladajme, že sme zavolali vyššie uvedený kód v jednovláknovom prostredí, aktualizovaná hodnota count bude 2. Ak zavoláme vyššie uvedenú metódu pomocou dvoch samostatných vlákien, obe pristupujú k premennej súčasne a tiež aktualizujú hodnotu počítať súčasne. Aby sme sa vyhli tejto situácii, používame atómovú operáciu.
kedy vyšiel windows 7
Java podporuje niekoľko typov atómových akcií, sú nasledovné:
- Prchavé premenných
- Nízkoúrovňové atómové operácie (nebezpečné)
- Atómové triedy
Pozrime sa, ako môžeme vytvoriť atómovú operáciu.
Atómová premenná
Atómová premenná nám umožňuje vykonať atómovú operáciu s premennou. Atómové premenné minimalizujú synchronizáciu a pomáhajú predchádzať chybám konzistencie pamäte. Zabezpečuje teda synchronizáciu.
Atómový balík poskytuje nasledujúcich päť atómových premenných:
- AtomicInteger
- AtomicLong
- AtomicBoolean
- AtomicIntegerArray
- AtomicLongArray
Potreba atómovej premennej
Zoberme si nasledujúci kód.
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'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't achieve the same.</td> <td>We can'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't achieve the same.</td> <td>We can't achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can't achieve the same.</td> <td>We can't achieve the same.</td> </tr> </table> <hr></max;></pre></max;>
Vyššie uvedený program poskytuje očakávaný výstup, ak sa vykonáva v prostredí s jedným vláknom. Viacvláknové prostredie môže viesť k neočakávanému výstupu. Dôvodom je, že keď sa dve alebo viac vlákien pokúša aktualizovať hodnotu súčasne, nemusí sa aktualizovať správne.
funkcia prototypu c++
Java ponúka dva riešenia na prekonanie tohto problému:
- Pomocou zámku a synchronizácie
- Pomocou atómovej premennej
Vytvorme program Java a pomocou atómovej premennej prekonáme problém.
Pomocou atómovej premennej
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't achieve the same.</td> <td>We can'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't achieve the same.</td> <td>We can't achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can't achieve the same.</td> <td>We can't achieve the same.</td> </tr> </table> <hr></max;>
Synchronizované vs. Atómový vs. Prchavé
Synchronizované | Atómový | Prchavé |
---|---|---|
Vzťahuje sa len na metódy. | Vzťahuje sa len na premenné. | Platí to len pre premenné. |
Zabezpečuje viditeľnosť spolu s atomicitou. | Zabezpečuje tiež viditeľnosť spolu s atomicitou. | Zabezpečuje viditeľnosť, nie atomicitu. |
Nemôžeme dosiahnuť to isté. | Nemôžeme dosiahnuť to isté. | Ukladá sa do pamäte RAM, takže prístup k nestálym premenným je rýchly. Neposkytuje však bezpečnosť vlákien a synchronizáciu. |
Môže byť implementovaný ako synchronizovaný blok alebo synchronizovaná metóda. | Nemôžeme dosiahnuť to isté. | Nemôžeme dosiahnuť to isté. |
Môže uzamknúť rovnaký objekt triedy alebo iný objekt triedy. | Nemôžeme dosiahnuť to isté. | Nemôžeme dosiahnuť to isté. |