Java valodā, atomu mainīgie un operācijas izmanto vienlaicīgi. The vairāku vītņu vide rada problēmas, kad vienlaicīgums ir vienota. Programmas izpildes laikā var tikt mainīta koplietotā entītija, piemēram, objekti un mainīgie. Tādējādi tie var izraisīt programmas nekonsekvenci. Tāpēc ir svarīgi rūpēties par koplietoto entītiju, vienlaikus piekļūstot. Šādos gadījumos, atomu mainīgais var būt risinājums tam. Šajā sadaļā mēs apspriedīsim atomu klases, atomu mainīgie, atomu darbības , kopā ar piemēriem.
xml komentārs
Pirms turpināt šajā sadaļā, pārliecinieties, ka esat informēts par pavediens , sinhronizācija , un slēdzene Java valodā.
Java atomu klases
Java nodrošina a java.util.concurrent.atomic pakete, kurā ir noteiktas atomu klases. Atomu klases nodrošina a bez slēdzenes un vītnes drošs vide vai programmēšana uz viena mainīgā lieluma. Tas atbalsta arī atomu darbības. Visām atomu klasēm ir metodes get () un set (), kas darbojas ar mainīgo mainīgo. Metode darbojas tāpat kā lasīšana un rakstīšana uz mainīgiem mainīgajiem.
Komplektā ir šādas atomu klases:
Klase | Apraksts |
---|---|
Atombūla | To izmanto, lai atomiski atjauninātu Būla vērtību. |
AtomicInteger | To izmanto, lai atomiski atjauninātu veselu skaitļu vērtību. |
AtomicIntegerArray | Int masīvs, kurā elementus var atjaunināt atomiski. |
AtomicIntegerFieldUpdater | Uz pārdomām balstīta utilīta, kas nodrošina atomu atjauninājumus norādīto klašu noteiktiem nepastāvīgajiem int laukiem. |
AtomicLong | To izmanto, lai atomiski atjauninātu garo vērtību. |
AtomicLongArray | Garš masīvs, kurā elementus var atjaunināt atomiski. |
AtomicLongFieldUpdater | Uz pārdomām balstīta utilīta, kas nodrošina atomu atjauninājumus noteiktos mainīgos garos noteikto klašu laukos. |
AtomicMarkableReference | AtomicMarkableReference saglabā objekta atsauci kopā ar atzīmes bitu, ko var atjaunināt atomiski. |
AtomicReference | Objekta atsauce, ko var atjaunināt atomiski. |
AtomicReferenceArray | Objektu atsauču masīvs, kurā elementus var atjaunināt atomiski. |
AtomicReferenceFieldUpdater | Uz pārdomām balstīta utilīta, kas nodrošina atomu atjauninājumus noteikto klašu norādītajos nepastāvīgos atsauces laukos. |
AtomicStampedReference | AtomicStampedReference saglabā objekta atsauci kopā ar vesela skaitļa “zīmogu”, ko var atjaunināt atomiski. |
DoubleAccumulator | Viens vai vairāki mainīgie, kas kopā uztur dubulto vērtību, kas tiek atjaunināta, izmantojot piegādāto funkciju. |
DoubleAdder | Viens vai vairāki mainīgie, kas kopā saglabā sākotnēji nulles dubulto summu. |
LongAkumulators | Viens vai vairāki mainīgie, kas kopā uztur ilgstošu vērtību, kas tiek atjaunināta, izmantojot piegādāto funkciju. |
LongAdder | Viens vai vairāki mainīgie, kas kopā saglabā sākotnēji nulles garo summu. |
Šo klašu objekti attēlo atomu mainīgo int, garš, Būla , un objekts atsauce attiecīgi. Atomu klasēm ir dažas kopīgas metodes:
Metodes | Apraksts |
---|---|
set() | To izmanto, lai iestatītu vērtību. |
gūt() | To izmanto, lai iegūtu pašreizējo vērtību. |
lazySet() | Galu galā tiek iestatīta norādītā vērtība. |
salīdzinātAndIestatīt | Atomiski iestata vērtību uz doto atjaunināto vērtību, ja pašreizējā vērtība == paredzamā vērtība. |
Atomu operācijas
Tās darbības, kuras vienmēr tiek izpildītas kopā, ir pazīstamas kā atomu operācijas vai atomu darbība . Visas atomu operācijas, kas tiek efektīvi izpildītas, notiek uzreiz vai nenotiek vispār. Trīs galvenie jēdzieni, kas saistīti ar atomu darbībām Java, ir šādi:
1. Atomiskums attiecas uz to, kādas darbības un darbību kopas ir neredzams Piemēram, apsveriet šādu koda fragmentu:
class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement }
Iepriekš minētajā kodā darbojas increment () un decrement () vienlaicīgi nenoteikts un nav paredzams .
2. Redzamība nosaka, kad var būt viena pavediena efekts redzēts ar citu. Piemēram, apsveriet šādu koda fragmentu:
sql servera pivot
class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements }
Iepriekš minētajā kodā ir iespējams, ka pavediens T2 nekad neapstāsies pat pēc tam, kad pavediens T1 ir iestatīts uz patiesu. Tāpat ne tas, ka starp pavedieniem nav sinhronizācijas.
3. Sakārtotība nosaka, kad darbības vienā pavedienā notiek ārpus secības attiecībā pret citu pavedienu.
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; } }
Secība, kādā lauki a un b parādās pavedienā T2, var atšķirties no secības, kādā tie tika iestatīti pavedienā T1.
Sapratīsim to, izmantojot piemēru.
public class AtomicExample { int count; public void incrementCount() { count=1; }
Iepriekš minētajā koda fragmentā esam deklarējuši int tipa mainīgo skaitīt un metodes incrementCount() iekšpusē to piešķīra 1. Šādā gadījumā vai nu viss notiek kopā, vai arī nenotiks vispār. Tādējādi tas apzīmē an atomu darbība un operācija ir pazīstama kā atomiskums .
Apsvērsim citu koda fragmentu.
public class AtomicExample { int count; public void incrementCount() { count=count+1; }
Šķiet, ka tā ir arī atomu darbība, bet ne tā. Tā ir lineāra darbība, kas sastāv no trim operācijām, t.i., lasīšanas, modificēšanas un rakstīšanas. Tāpēc to var izpildīt daļēji. Bet, ja mēs izmantojam iepriekš minēto kodu daudzpavedienu vidē, tas rada problēmu.
Pieņemsim, ka mēs esam izsaukuši iepriekš minēto kodu viena pavediena vidē, atjauninātā skaita vērtība būs 2. Ja mēs izsaucam iepriekš minēto metodi, izmantojot divus atsevišķus pavedienus, tie abi piekļūst mainīgajam vienlaikus un arī atjaunina skaitīt vienlaicīgi. Lai izvairītos no šādas situācijas, mēs izmantojam atomu darbību.
string in int
Java atbalsta vairāku veidu atomu darbības, kas ir šādas:
- Nepastāvīgs mainīgie
- Zema līmeņa atomu operācijas (nedrošas)
- Atomu klases
Apskatīsim, kā mēs varam izveidot atomu darbību.
Atomu mainīgais
Atomu mainīgais ļauj mums veikt atomu darbību ar mainīgo. Atomiskie mainīgie samazina sinhronizāciju un palīdz izvairīties no atmiņas konsekvences kļūdām. Tādējādi tas nodrošina sinhronizāciju.
Atomu pakete nodrošina šādus piecus atomu mainīgos lielumus:
indiešu aktrise Rani Mukerji
- AtomicInteger
- AtomicLong
- Atombūla
- AtomicIntegerArray
- AtomicLongArray
Nepieciešamība pēc atomu mainīgā
Apskatīsim šādu kodu.
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;>
Iepriekš minētā programma sniedz paredzamo izvadi, ja tā tiek izpildīta viena pavediena vidē. Vairāku pavedienu vide var radīt neparedzētu izvadi. Iemesls tam, ka, ja divi vai vairāki pavedieni mēģina atjaunināt vērtību vienlaikus, tas var netikt atjaunināts pareizi.
Java piedāvājumi divi risinājumi šīs problēmas pārvarēšanai:
- Izmantojot bloķēšanu un sinhronizāciju
- Izmantojot atomu mainīgo
Izveidosim Java programmu un izmantosim atomu mainīgo, lai pārvarētu problēmu.
Izmantojot 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;>
Sinhronizēts vs. Atomu vs. Nepastāvīgs
Sinhronizēts | Atomisks | Nepastāvīgs |
---|---|---|
Tas attiecas tikai uz metodēm. | Tas attiecas tikai uz mainīgajiem. | Tas attiecas arī tikai uz mainīgajiem. |
Tas nodrošina redzamību kopā ar atomitāti. | Tas arī nodrošina redzamību kopā ar atomitāti. | Tas nodrošina redzamību, nevis atomitāti. |
Mēs nevaram sasniegt to pašu. | Mēs nevaram sasniegt to pašu. | Tas tiek glabāts RAM, tāpēc piekļuve mainīgajiem mainīgajiem ir ātra. Bet tas nenodrošina pavedienu drošību un sinhronizāciju. |
To var realizēt kā sinhronizētu bloku vai sinhronizētu metodi. | Mēs nevaram sasniegt to pašu. | Mēs nevaram sasniegt to pašu. |
Tas var bloķēt vienu un to pašu klases objektu vai citu klases objektu. | Mēs nevaram sasniegt to pašu. | Mēs nevaram sasniegt to pašu. |