logo

Java atomico

A Giava, variabili atomiche E operazioni utilizzati in concomitanza. IL multithreading l'ambiente porta a un problema quando concorrenza è unificato. Le entità condivise come oggetti e variabili possono essere modificate durante l'esecuzione del programma. Pertanto, potrebbero portare a incoerenze del programma. Pertanto, è importante prendersi cura dell'entità condivisa durante l'accesso simultaneo. In tali casi, il variabile atomica può essere una soluzione al problema. In questa sezione discuteremo classi atomiche, variabili atomiche, operazioni atomiche , insieme ad esempi.

cos'è l'ibernazione

Prima di procedere in questa sezione, assicurati di esserne a conoscenza filo , sincronizzazione , E serratura a Giava.

Classi atomiche Java

Giava fornisce un java.util.concurrent.atomic pacchetto in cui sono definite le classi atomiche. Le classi atomiche forniscono a senza serratura E thread-safe ambiente o programmazione su una singola variabile. Supporta anche le operazioni atomiche. Tutte le classi atomiche hanno i metodi get() e set() che funzionano sulla variabile volatile. Il metodo funziona allo stesso modo di read e scrive su variabili volatili.

Il pacchetto fornisce le seguenti classi atomiche:

Classe Descrizione
AtomicBoolean Viene utilizzato per aggiornare atomicamente il valore booleano.
AtomicInteger Viene utilizzato per aggiornare atomicamente il valore intero.
AtomicIntegerArray Un array int in cui gli elementi possono essere aggiornati atomicamente.
AtomicIntegerFieldUpdater Un'utilità basata sulla riflessione che consente aggiornamenti atomici ai campi int volatili designati delle classi designate.
AtomicLong Viene utilizzato per aggiornare atomicamente il valore lungo.
AtomicLongArray Un lungo array in cui gli elementi possono essere aggiornati atomicamente.
AtomicLongFieldUpdater Un'utilità basata sulla riflessione che consente aggiornamenti atomici su campi lunghi volatili designati di classi designate.
AtomicMarkableReference Un AtomicMarkableReference mantiene un riferimento all'oggetto insieme a un bit di contrassegno, che può essere aggiornato atomicamente.
Riferimento atomico Un riferimento a un oggetto che può essere aggiornato atomicamente.
AtomicReferenceArray Un array di riferimenti a oggetti in cui gli elementi possono essere aggiornati atomicamente.
AtomicReferenceFieldUpdater Un'utilità basata sulla riflessione che consente aggiornamenti atomici su campi di riferimento volatili designati di classi designate.
AtomicStampedReference Un AtomicStampedReference mantiene un riferimento all'oggetto insieme a un 'timbro' intero, che può essere aggiornato atomicamente.
Doppio accumulatore Una o più variabili che insieme mantengono un valore double corrente aggiornato utilizzando una funzione fornita.
DoubleAdder Una o più variabili che insieme mantengono una doppia somma inizialmente nulla.
LongAccumulatore Una o più variabili che insieme mantengono un valore running long aggiornato utilizzando una funzione fornita.
LongAdder Una o più variabili che insieme mantengono una somma lunga inizialmente pari a zero.

Gli oggetti di queste classi rappresentano la variabile atomica di int, lungo, booleano e oggetto riferimento rispettivamente. Le classi atomiche hanno alcuni metodi comuni sono i seguenti:

Metodi Descrizione
impostato() Viene utilizzato per impostare il valore.
Ottenere() Viene utilizzato per ottenere il valore corrente.
lazySet() Alla fine viene impostato sul valore specificato.
confrontareAndSet Imposta atomicamente il valore sul valore aggiornato specificato se il valore corrente == il valore previsto.

Operazioni atomiche

Quelle operazioni che vengono sempre eseguite insieme sono note come operazioni atomiche O azione atomica . Tutte le operazioni atomiche vengono effettivamente eseguite tutte in una volta oppure non vengono eseguite affatto. Tre i concetti chiave associati alle azioni atomiche in Java sono i seguenti:

1. L'atomicità si occupa di quali azioni e insiemi di azioni hanno invisibile Ad esempio, considera il seguente frammento di codice:

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

Nel codice precedente, il comportamento dell'esecuzione simultanea di incrementa() e decrement() è non definito E non prevedibile .

2. La visibilità determina quando può essere l'effetto di un thread visto da un altro. Ad esempio, considera il seguente frammento di codice:

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

Nel codice precedente, è possibile che il thread T2 non si interrompa mai anche dopo che il thread T1 è stato impostato su true. Inoltre, non che non vi sia sincronizzazione tra i thread.

3. L'ordinamento determina quando le azioni in un thread si verificano fuori ordine rispetto a un altro thread.

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

L'ordine in cui i campi aeb appaiono nel thread T2 può differire dall'ordine in cui sono stati impostati nel thread T1.

guasto generale di protezione

Capiamolo attraverso un esempio.

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

Nel frammento di codice sopra, abbiamo dichiarato una variabile di tipo int contare e all'interno del metodo incrementaCount() lo ha assegnato a 1. In tal caso, o accadono tutti insieme o non accadrebbero affatto. Quindi, rappresenta un operazione atomica e l'operazione è nota come atomicita .

Consideriamo un altro frammento di codice.

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

Sembra che sia anche un'operazione atomica ma non è così. È un'operazione lineare composta da tre operazioni, ovvero lettura, modifica e scrittura. Pertanto, può essere eseguito parzialmente. Ma se utilizziamo il codice precedente in un ambiente multi-thread, ciò crea un problema.

Supponiamo di aver chiamato il codice precedente in un ambiente a thread singolo, il valore aggiornato di count sarà 2. Se chiamiamo il metodo precedente da due thread separati, entrambi accedono alla variabile contemporaneamente e aggiornano anche il valore di contare contemporaneamente. Per evitare questa situazione, utilizziamo l'operazione atomica.

tutorial su ssis

Java supporta diversi tipi di azioni atomiche, sono le seguenti:

  • Volatile variabili
  • Operazioni atomiche di basso livello (non sicure)
  • Classi atomiche

Vediamo come possiamo creare un'operazione atomica.

Variabile atomica

La variabile atomica ci consente di eseguire un'operazione atomica su una variabile. Le variabili atomiche riducono al minimo la sincronizzazione e aiutano a evitare errori di coerenza della memoria. Quindi, garantisce la sincronizzazione.

Il pacchetto atomico fornisce le seguenti cinque variabili atomiche:

  • AtomicInteger
  • AtomicLong
  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLongArray

La necessità della variabile atomica

Consideriamo il seguente codice.

mappa dattiloscritta

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

Il programma precedente fornisce l'output previsto se viene eseguito in un ambiente a thread singolo. Un ambiente multi-thread può portare a risultati imprevisti. Il motivo è che quando due o più thread tentano di aggiornare il valore contemporaneamente, potrebbe non aggiornarsi correttamente.

Offerte Java due soluzioni per superare questo problema:

  • Utilizzando il blocco e la sincronizzazione
  • Utilizzando la variabile atomica

Creiamo un programma Java e utilizziamo una variabile atomica per superare il problema.

Utilizzando la variabile atomica

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

Sincronizzato vs. Atomico vs. Volatile

Sincronizzato Atomico Volatile
Si applica solo ai metodi. Si applica solo alle variabili. Si applica anche solo alle variabili.
Garantisce visibilità insieme all'atomicità. Garantisce inoltre la visibilità insieme all'atomicità. Garantisce visibilità, non atomicità.
Non possiamo ottenere lo stesso. Non possiamo ottenere lo stesso. Memorizza nella RAM, quindi l'accesso alle variabili volatili è veloce. Ma non fornisce sicurezza e sincronizzazione del thread.
Può essere implementato come blocco sincronizzato o metodo sincronizzato. Non possiamo ottenere lo stesso. Non possiamo ottenere lo stesso.
Può bloccare lo stesso oggetto di classe o un oggetto di classe diverso. Non possiamo ottenere lo stesso. Non possiamo ottenere lo stesso.