În Java, variabile atomice și operațiuni folosit în concurență. The multi-threading mediu duce la o problemă când concurență este unificat. Entitatea partajată, cum ar fi obiectele și variabilele, poate fi modificată în timpul execuției programului. Prin urmare, acestea pot duce la inconsecvența programului. Deci, este important să aveți grijă de entitatea partajată în timp ce accesați simultan. În astfel de cazuri, variabilă atomică poate fi o soluție la asta. În această secțiune, vom discuta clase atomice, variabile atomice, operații atomice , împreună cu exemple.
lista de sortare java
Înainte de a continua în această secțiune, asigurați-vă că sunteți la curent fir , sincronizare , și Lacăt în Java.
Clasele atomice Java
Java prevede a java.util.concurrent.atomic pachet în care sunt definite clase atomice. Clasele atomice oferă a fără blocare și fir de siguranta mediu sau programare pe o singură variabilă. De asemenea, suportă operațiuni atomice. Toate clasele atomice au metodele get() și set() care funcționează asupra variabilei volatile. Metoda funcționează la fel ca citirea și scrierea pe variabile volatile.
Pachetul oferă următoarele clase atomice:
Clasă | Descriere |
---|---|
AtomicBoolean | Este folosit pentru a actualiza valoarea booleană atomic. |
AtomicInteger | Este folosit pentru a actualiza atomic valoarea întregului. |
AtomicIntegerArray | O matrice int în care elementele pot fi actualizate atomic. |
AtomicIntegerFieldUpdater | Un utilitar bazat pe reflectare care permite actualizări atomice ale câmpurilor int volatile desemnate ale claselor desemnate. |
AtomicLong | Este folosit pentru a actualiza valoarea lungă atomic. |
AtomicLongArray | O matrice lungă în care elementele pot fi actualizate atomic. |
AtomicLongFieldUpdater | Un utilitar bazat pe reflectare care permite actualizări atomice ale câmpurilor lungi volatile desemnate ale claselor desemnate. |
AtomicMarkableReference | O referință AtomicMarkableReference menține o referință de obiect împreună cu un bit de marcare, care poate fi actualizat atomic. |
AtomicReference | O referință la obiect care poate fi actualizată atomic. |
AtomicReferenceArray | O serie de referințe la obiecte în care elementele pot fi actualizate atomic. |
AtomicReferenceFieldUpdater | Un utilitar bazat pe reflectare care permite actualizări atomice ale câmpurilor de referință volatile desemnate ale claselor desemnate. |
AtomicStampedReference | Un AtomicStampedReference menține o referință la obiect împreună cu un „ștampil” întreg, care poate fi actualizat atomic. |
DoubleAccumulator | Una sau mai multe variabile care împreună mențin o valoare dublă curentă actualizată folosind o funcție furnizată. |
DoubleAdder | Una sau mai multe variabile care împreună mențin o sumă dublă inițial zero. |
Acumulator lung | Una sau mai multe variabile care împreună mențin o valoare lungă de rulare actualizată folosind o funcție furnizată. |
LongAdder | Una sau mai multe variabile care împreună mențin o sumă lungă inițial zero. |
Obiectele acestor clase reprezintă variabila atomică a int, lung, boolean , și obiect referinţă respectiv. Clasele atomice au câteva metode comune, după cum urmează:
Metode | Descriere |
---|---|
a stabilit() | Este folosit pentru a seta valoarea. |
obține() | Este folosit pentru a obține valoarea curentă. |
lazySet() | În cele din urmă se setează la valoarea dată. |
compareAndSet | Setează atomic valoarea la valoarea actualizată dată dacă valoarea curentă == valoarea așteptată. |
Operațiuni atomice
Acele operațiuni care se execută întotdeauna împreună sunt cunoscute sub numele de operatii atomice sau acţiunea atomică . Toate operațiunile atomice fie executate efectiv se întâmplă dintr-o dată, fie nu se întâmplă deloc. Trei conceptele cheie sunt asociate cu acțiunile atomice în Java sunt după cum urmează:
1. Atomicitatea se ocupă de ce acțiuni și seturi de acțiuni au invizibil De exemplu, luați în considerare următorul fragment de cod:
class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement }
În codul de mai sus, comportamentul rulării simultane a increment() și decrement() este nedefinit și nu previzibil .
2. Vizibilitatea determină când poate fi efectul unui fir văzut de altul. De exemplu, luați în considerare următorul fragment de cod:
port de ascultare
class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements }
În codul de mai sus, este posibil ca threadul T2 să nu se oprească niciodată chiar și după ce threadul T1 se setează la adevărat. De asemenea, nu că nu există sincronizare între fire.
3. Ordonarea determină momentul în care acțiunile dintr-un fir de execuție apar neregulate în raport cu un alt fir de execuție.
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; } }
Ordinea în care câmpurile a și b apar în firul T2 poate diferi de ordinea în care au fost stabilite în firul T1.
Să înțelegem printr-un exemplu.
public class AtomicExample { int count; public void incrementCount() { count=1; }
În fragmentul de cod de mai sus, am declarat o variabilă de tip int numara iar în interiorul metodei incrementCount() a atribuit-o la 1. Într-un astfel de caz, fie toate se întâmplă împreună, fie nu s-ar întâmpla deloc. Prin urmare, reprezintă un operare atomică iar operația este cunoscută ca atomicitate .
Să luăm în considerare un alt fragment de cod.
public class AtomicExample { int count; public void incrementCount() { count=count+1; }
Se pare că este și o operațiune atomică, dar nu așa. Este o operație liniară care constă din trei operații, adică citire, modificare și scriere. Prin urmare, se poate executa parțial. Dar dacă folosim codul de mai sus într-un mediu cu mai multe fire, creează o problemă.
Să presupunem că am apelat codul de mai sus într-un mediu cu un singur thread, valoarea actualizată a numărului va fi 2. Dacă apelăm metoda de mai sus prin două fire separate, ambele accesează variabila în același timp și, de asemenea, actualizează valoarea lui numără simultan. Pentru a evita această situație, folosim operația atomică.
tutorial react js
Java acceptă mai multe tipuri de acțiuni atomice, după cum urmează:
- Volatil variabile
- Operații atomice la nivel scăzut (nesigure)
- Clasele atomice
Să vedem cum putem crea o operație atomică.
Variabilă atomică
Variabila atomică ne permite să efectuăm o operație atomică asupra unei variabile. Variabilele atomice minimizează sincronizarea și ajută la evitarea erorilor de consistență a memoriei. Prin urmare, asigură sincronizarea.
Pachetul atomic oferă următoarele cinci variabile atomice:
java dublu la șir
- AtomicInteger
- AtomicLong
- AtomicBoolean
- AtomicIntegerArray
- AtomicLongArray
Nevoia de variabilă atomică
Să luăm în considerare următorul cod.
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;>
Programul de mai sus oferă rezultatul așteptat dacă este executat într-un mediu cu un singur thread. Un mediu cu mai multe fire poate duce la rezultate neașteptate. Motivul din spatele acestuia este că atunci când două sau mai multe fire de execuție încearcă să actualizeze valoarea în același timp, este posibil să nu se actualizeze corect.
Oferte Java Două soluții pentru a depăși această problemă:
- Prin utilizarea blocării și sincronizării
- Prin utilizarea variabilei atomice
Să creăm un program Java și să folosim o variabilă atomică pentru a depăși problema.
Prin utilizarea variabilei atomice
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;>
Sincronizat vs. Atomic vs. Volatil
Sincronizat | Atomic | Volatil |
---|---|---|
Se aplică numai metodelor. | Se aplică numai variabilelor. | De asemenea, se aplică numai variabilelor. |
Asigură vizibilitatea împreună cu atomicitatea. | De asemenea, asigură vizibilitatea împreună cu atomicitatea. | Asigură vizibilitate, nu atomicitate. |
Nu putem realiza același lucru. | Nu putem realiza același lucru. | Se stochează în RAM, deci accesarea variabilelor volatile este rapidă. Dar nu oferă siguranța firelor și sincronizarea. |
Poate fi implementat ca un bloc sincronizat sau o metodă sincronizată. | Nu putem realiza același lucru. | Nu putem realiza același lucru. |
Poate bloca același obiect de clasă sau un obiect de clasă diferit. | Nu putem realiza același lucru. | Nu putem realiza același lucru. |