I Java, atomvariabler og operasjoner brukes samtidig. De flertråding miljø fører til et problem når samtidighet er samlet. Den delte enheten som objekter og variabler kan endres under kjøringen av programmet. Derfor kan de føre til inkonsekvens i programmet. Så det er viktig å ta vare på den delte enheten mens du har tilgang samtidig. I slike tilfeller vil atomvariabel kan være en løsning på det. I denne delen vil vi diskutere atomklasser, atomvariabler, atomoperasjoner , sammen med eksempler.
np.linspace
Før du går videre i denne delen, sørg for at du er klar over tråd , synkronisering , og låse i Java.
Java Atomic Klasser
Java gir en java.util.samtidig.atomisk pakke der atomklasser er definert. Atomklassene gir en låsefri og trådsikker miljø eller programmering på en enkelt variabel. Den støtter også atomoperasjoner. Alle atomklassene har metodene get() og set() som fungerer på den flyktige variabelen. Metoden fungerer på samme måte som å lese og skrive på flyktige variabler.
Pakken inneholder følgende atomklasser:
Klasse | Beskrivelse |
---|---|
AtomicBoolean | Den brukes til å oppdatere boolsk verdi atomært. |
AtomicInteger | Den brukes til å oppdatere heltallsverdi atomisk. |
AtomicIntegerArray | En int-matrise der elementer kan oppdateres atomisk. |
AtomicIntegerFieldUpdater | Et refleksjonsbasert verktøy som muliggjør atomoppdateringer til utpekte flyktige int-felt av utpekte klasser. |
AtomicLong | Den brukes til å oppdatere lang verdi atomisk. |
AtomicLongArray | En lang rekke der elementer kan oppdateres atomisk. |
AtomicLongFieldUpdater | Et refleksjonsbasert verktøy som muliggjør atomoppdateringer til utpekte flyktige lange felt av utpekte klasser. |
AtomicMarkableReference | En AtomicMarkableReference opprettholder en objektreferanse sammen med en merkebit, som kan oppdateres atomisk. |
AtomicReference | En objektreferanse som kan oppdateres atomisk. |
AtomicReferenceArray | En rekke objektreferanser der elementer kan oppdateres atomisk. |
AtomicReferenceFieldUpdater | Et refleksjonsbasert verktøy som muliggjør atomoppdateringer til utpekte flyktige referansefelt for utpekte klasser. |
AtomicStampedReference | En AtomicStampedReference opprettholder en objektreferanse sammen med et heltalls 'stempel', som kan oppdateres atomisk. |
Dobbeltakkumulator | En eller flere variabler som sammen opprettholder en løpende dobbel verdi oppdatert ved hjelp av en medfølgende funksjon. |
DoubleAdder | En eller flere variabler som sammen opprettholder en i utgangspunktet null dobbeltsum. |
Lang akkumulator | En eller flere variabler som sammen opprettholder en løpende lang verdi oppdatert ved hjelp av en medfølgende funksjon. |
LongAdder | En eller flere variabler som sammen opprettholder en i utgangspunktet null lang sum. |
Objekter av disse klassene representerer atomvariabelen til int, lang, boolsk , og objekt henvisning hhv. Atomklassene har noen vanlige metoder er som følger:
Metoder | Beskrivelse |
---|---|
sett() | Den brukes til å angi verdien. |
få() | Den brukes til å få gjeldende verdi. |
lazySet() | Settes til slutt til den gitte verdien. |
compareAndSet | Atomically setter verdien til den gitte oppdaterte verdien hvis gjeldende verdi == forventet verdi. |
Atomiske operasjoner
De operasjonene som alltid utføres sammen er kjent som atomoperasjoner eller atomvirkning . Alle atomoperasjoner som enten utføres effektivt skjer alt på en gang, eller så skjer det ikke i det hele tatt. Tre nøkkelbegreper som er assosiert med atomiske handlinger i Java er som følger:
1. Atomicity omhandler hvilke handlinger og sett o handlinger har usynlig Tenk for eksempel på følgende kodebit:
class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement }
I koden ovenfor er oppførselen til å kjøre increment() og decrement() samtidig udefinert og ikke forutsigbar .
2. Synlighet avgjør når effekten av en tråd kan være sett av en annen. Tenk for eksempel på følgende kodebit:
class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements }
I koden ovenfor er det mulig at tråd T2 aldri stopper selv etter at tråd T1 er satt til sann. Heller ikke at det ikke er noen synkronisering mellom tråder.
3. Rekkefølge avgjør når handlinger i en tråd skjer i uorden i forhold til en annen tråd.
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; } }
Rekkefølgen som felt a og b vises i tråd T2 kan avvike fra rekkefølgen de ble satt i tråd T1.
liste til array java
La oss forstå det gjennom et eksempel.
public class AtomicExample { int count; public void incrementCount() { count=1; }
I kodebiten ovenfor har vi erklært en variabel av typen int telle og inne i metoden incrementCount() tildelte den til 1. I et slikt tilfelle skjer enten alt sammen eller vil ikke skje i det hele tatt. Derfor representerer det en atomdrift og operasjonen er kjent som atomitet .
La oss vurdere en annen kodebit.
public class AtomicExample { int count; public void incrementCount() { count=count+1; }
Det ser ut til at det også er en atomoperasjon, men ikke så. Det er en lineær operasjon som består av tre operasjoner, dvs. lese, endre og skrive. Derfor kan den utføres delvis. Men hvis vi bruker koden ovenfor i et flertrådsmiljø, skaper det et problem.
Anta at vi har kalt koden ovenfor i et enkelt-tråds miljø, vil den oppdaterte verdien av count være 2. Hvis vi kaller metoden ovenfor med to separate tråder, får de både tilgang til variabelen samtidig og oppdaterer også verdien av telle samtidig. For å unngå denne situasjonen bruker vi atomdrift.
java lokal datotid
Java støtter flere typer atomhandlinger, er som følger:
- Flyktige variabler
- Atomoperasjoner på lavt nivå (utrygge)
- Atomklasser
La oss se hvordan vi kan lage en atomoperasjon.
Atomvariabel
Atomvariabelen lar oss utføre en atomoperasjon på en variabel. Atomvariabler minimerer synkronisering og bidrar til å unngå minnekonsistensfeil. Derfor sikrer det synkronisering.
.neste java
Atompakken gir følgende fem atomvariabler:
- AtomicInteger
- AtomicLong
- AtomicBoolean
- AtomicIntegerArray
- AtomicLongArray
Behovet for atomvariabel
La oss vurdere følgende kode.
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;>
Programmet ovenfor gir forventet utgang hvis det kjøres i et enkelt-tråds miljø. Et flertrådsmiljø kan føre til uventede utdata. Årsaken bak det at når to eller flere tråder prøver å oppdatere verdien samtidig, kan det hende at den ikke oppdateres riktig.
Java tilbyr to løsninger for å løse dette problemet:
- Ved å bruke lås og synkronisering
- Ved å bruke atomvariabel
La oss lage et Java-program og bruke en atomvariabel for å løse problemet.
Ved å bruke Atomic Variable
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;>
Synkronisert vs. Atomic vs. Flyktige
Synkronisert | Atomisk | Flyktige |
---|---|---|
Det gjelder kun metoder. | Det gjelder kun variabler. | Det gjelder også kun for variabler. |
Det sikrer synlighet sammen med atomitet. | Det sikrer også synlighet sammen med atomitet. | Det sikrer synlighet, ikke atomitet. |
Vi kan ikke oppnå det samme. | Vi kan ikke oppnå det samme. | Den lagrer i RAM, så tilgang til flyktige variabler er rask. Men det gir ikke trådsikkerhet og synkronisering. |
Den kan implementeres som en synkronisert blokk eller en synkronisert metode. | Vi kan ikke oppnå det samme. | Vi kan ikke oppnå det samme. |
Den kan låse det samme klasseobjektet eller et annet klasseobjekt. | Vi kan ikke oppnå det samme. | Vi kan ikke oppnå det samme. |