logo

Java Atômico

Em Java, variáveis ​​atômicas e operações usado em simultaneidade. O multithreading ambiente leva a um problema quando simultaneidade é unificado. A entidade compartilhada, como objetos e variáveis, pode ser alterada durante a execução do programa. Conseqüentemente, eles podem levar à inconsistência do programa. Portanto, é importante cuidar da entidade compartilhada ao acessar simultaneamente. Nesses casos, o variável atômica pode ser uma solução para isso. Nesta seção, discutiremos classes atômicas, variáveis ​​atômicas, operações atômicas , junto com exemplos.

concha bourne-novamente

Antes de prosseguir nesta seção, certifique-se de estar ciente de fio , sincronização , e trancar em Java.

Classes Atômicas Java

Java Fornece uma java.util.concurrent.atomic pacote no qual as classes atômicas são definidas. As classes atômicas fornecem uma sem bloqueio e discussão segura ambiente ou programação em uma única variável. Ele também oferece suporte a operações atômicas. Todas as classes atômicas possuem os métodos get() e set() que funcionam na variável volátil. O método funciona da mesma forma que ler e escrever em variáveis ​​voláteis.

O pacote fornece as seguintes classes atômicas:

Aula Descrição
AtômicoBooleano É usado para atualizar o valor booleano atomicamente.
Número inteiro atômico É usado para atualizar o valor inteiro atomicamente.
AtomicIntegerArray Uma matriz int na qual os elementos podem ser atualizados atomicamente.
AtomicIntegerFieldUpdater Um utilitário baseado em reflexão que permite atualizações atômicas para campos int voláteis designados de classes designadas.
Atômico Longo É usado para atualizar valores longos atomicamente.
AtômicoLongArray Uma longa matriz na qual os elementos podem ser atualizados atomicamente.
AtomicLongFieldUpdater Um utilitário baseado em reflexão que permite atualizações atômicas para campos longos voláteis designados de classes designadas.
Referência AtômicaMarkable Um AtomicMarkableReference mantém uma referência de objeto junto com um bit de marca, que pode ser atualizado atomicamente.
Referência Atômica Uma referência de objeto que pode ser atualizada atomicamente.
Array de referência atômica Uma matriz de referências de objetos nas quais os elementos podem ser atualizados atomicamente.
AtomicReferenceFieldUpdater Um utilitário baseado em reflexão que permite atualizações atômicas para campos de referência voláteis designados de classes designadas.
Referência Atômica Estampada Um AtomicStampedReference mantém uma referência de objeto junto com um 'carimbo' inteiro, que pode ser atualizado atomicamente.
Acumulador Duplo Uma ou mais variáveis ​​que juntas mantêm um valor duplo em execução atualizado usando uma função fornecida.
DoubleAdder Uma ou mais variáveis ​​que juntas mantêm uma soma dupla inicialmente zero.
Acumulador Longo Uma ou mais variáveis ​​que juntas mantêm um valor longo atualizado usando uma função fornecida.
LongAdder Uma ou mais variáveis ​​que juntas mantêm uma soma longa inicialmente zero.

Os objetos dessas classes representam a variável atômica de int, longo, booleano e objeto referência respectivamente. As classes atômicas têm alguns métodos comuns:

Métodos Descrição
definir() É usado para definir o valor.
pegar() É usado para obter o valor atual.
preguiçosoSet() Eventualmente define para o valor fornecido.
compareAndSet Define atomicamente o valor para o valor atualizado fornecido se o valor atual == o valor esperado.

Operações Atômicas

Aquelas operações que sempre são executadas juntas são conhecidas como operações atômicas ou ação atômica . Todas as operações atômicas executadas efetivamente acontecem de uma só vez ou nem acontecem. Três os principais conceitos associados às ações atômicas em Java são os seguintes:

1. A atomicidade trata de quais ações e conjuntos de ações têm invisível Por exemplo, considere o seguinte trecho de código:

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

No código acima, o comportamento de executar increment() e decrement() simultaneamente é indefinido e não previsível .

2. A visibilidade determina quando o efeito de um fio pode ser visto por outro. Por exemplo, considere o seguinte trecho de código:

como bloquear anúncios do youtube no android
 class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements } 

No código acima, é possível que o thread T2 nunca pare mesmo depois que o thread T1 definir feito como verdadeiro. Além disso, não que não haja sincronização entre threads.

3. A ordem determina quando as ações em um thread ocorrem fora de ordem em relação a outro 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; } } 

A ordem em que os campos aeb aparecem no thread T2 pode ser diferente da ordem em que foram definidos no thread T1.

Vamos entender isso através de um exemplo.

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

No trecho de código acima, declaramos uma variável do tipo int contar e dentro do método incrementCount() atribuiu-o a 1. Nesse caso, tudo aconteceria junto ou nem aconteceria. Portanto, representa um operação atômica e a operação é conhecida como atomicidade .

Vamos considerar outro trecho de código.

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

Parece que também é uma operação atômica, mas não é assim. É uma operação linear que consiste em três operações, ou seja, ler, modificar e escrever. Portanto, pode ser executado parcialmente. Mas se estivermos usando o código acima em um ambiente multithread, isso criará um problema.

Suponha que chamamos o código acima em um ambiente de thread único, o valor atualizado de count será 2. Se chamarmos o método acima por dois threads separados, ambos acessam a variável ao mesmo tempo e também atualizam o valor de contar simultaneamente. Para evitar esta situação, usamos a operação atômica.

loop aprimorado em java

Java suporta vários tipos de ações atômicas, são as seguintes:

  • Volátil variáveis
  • Operações atômicas de baixo nível (inseguras)
  • Aulas atômicas

Vamos ver como podemos criar uma operação atômica.

como imprimir java

Variável Atômica

A variável atômica nos permite realizar uma operação atômica em uma variável. Variáveis ​​atômicas minimizam a sincronização e ajudam a evitar erros de consistência de memória. Conseqüentemente, ele garante a sincronização.

O pacote atomic fornece as seguintes cinco variáveis ​​atômicas:

  • Número inteiro atômico
  • Atômico Longo
  • AtômicoBooleano
  • AtomicIntegerArray
  • AtômicoLongArray

A necessidade da variável atômica

Vamos considerar o seguinte código.

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

O programa acima fornece a saída esperada se for executado em um ambiente de thread único. Um ambiente multithread pode levar a resultados inesperados. A razão por trás disso é que quando dois ou mais threads tentam atualizar o valor ao mesmo tempo, ele pode não ser atualizado corretamente.

Ofertas Java dois soluções para superar esse problema:

  • Usando bloqueio e sincronização
  • Usando variável atômica

Vamos criar um programa Java e usar uma variável atômica para superar o problema.

Usando variável atômica

Exemplo Atômico.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;>

Sincronizado vs. Atômico vs. Volátil

Sincronizado Atômico Volátil
Aplica-se apenas a métodos. Aplica-se apenas a variáveis. Também se aplica apenas a variáveis.
Ele garante visibilidade junto com atomicidade. Ele também garante visibilidade junto com atomicidade. Garante visibilidade, não atomicidade.
Não podemos conseguir o mesmo. Não podemos conseguir o mesmo. Ele é armazenado na RAM, portanto, o acesso às variáveis ​​voláteis é rápido. Mas não fornece sincronização e segurança de thread.
Pode ser implementado como um bloco sincronizado ou um método sincronizado. Não podemos conseguir o mesmo. Não podemos conseguir o mesmo.
Ele pode bloquear o mesmo objeto de classe ou um objeto de classe diferente. Não podemos conseguir o mesmo. Não podemos conseguir o mesmo.