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