logo

Java atómico

En Java, variables atómicas y operaciones utilizado en concurrencia. El subprocesos múltiples El entorno genera un problema cuando concurrencia está unificado. La entidad compartida, como objetos y variables, puede cambiarse durante la ejecución del programa. Por lo tanto, pueden dar lugar a inconsistencia del programa. Por lo tanto, es importante cuidar la entidad compartida mientras se accede simultáneamente. En tales casos, el variable atómica puede ser una solución. En esta sección, discutiremos clases atómicas, variables atómicas, operaciones atómicas , junto con ejemplos.

matemáticas.pow java

Antes de continuar con esta sección, asegúrese de conocer hilo , sincronización , y cerrar en Java.

Clases atómicas de Java

Java provee un java.util.concurrent.atomic Paquete en el que se definen clases atómicas. Las clases atómicas proporcionan una sin cerradura y a salvo de amenazas entorno o programación en una sola variable. También soporta operaciones atómicas. Todas las clases atómicas tienen los métodos get() y set() que funcionan en la variable volátil. El método funciona igual que la lectura y escritura en variables volátiles.

El paquete proporciona las siguientes clases atómicas:

Clase Descripción
AtómicoBooleano Se utiliza para actualizar el valor booleano de forma atómica.
Entero atómico Se utiliza para actualizar el valor entero de forma atómica.
AtomicIntegerArray Una matriz int en la que los elementos pueden actualizarse atómicamente.
AtomicIntegerFieldUpdater Una utilidad basada en reflexión que permite actualizaciones atómicas de campos int volátiles designados de clases designadas.
atómicolargo Se utiliza para actualizar el valor largo de forma atómica.
AtómicoLongArray Una larga matriz en la que los elementos pueden actualizarse atómicamente.
Actualizador AtomicLongField Una utilidad basada en reflexión que permite actualizaciones atómicas de campos largos volátiles designados de clases designadas.
Referencia atómicamarcable Un AtomicMarkableReference mantiene una referencia de objeto junto con un bit de marca, que se puede actualizar atómicamente.
Referencia Atómica Una referencia de objeto que puede actualizarse atómicamente.
Matriz de referencia atómica Una matriz de referencias de objetos en la que los elementos pueden actualizarse atómicamente.
Actualizador de campo de referencia atómica Una utilidad basada en reflexión que permite actualizaciones atómicas de campos de referencia volátiles designados de clases designadas.
Referencia Atómica Estampada Un AtomicStampedReference mantiene una referencia de objeto junto con un 'sello' entero, que se puede actualizar atómicamente.
Doble acumulador Una o más variables que juntas mantienen un valor doble en ejecución actualizado mediante una función proporcionada.
Doble sumador Una o más variables que juntas mantienen una doble suma inicialmente cero.
Acumulador largo Una o más variables que juntas mantienen un valor largo en ejecución actualizado mediante una función proporcionada.
sumador largo Una o más variables que juntas mantienen una suma larga inicialmente cero.

Los objetos de estas clases representan la variable atómica de int, largo, booleano y objeto referencia respectivamente. Las clases atómicas tienen algunos métodos comunes que son los siguientes:

Métodos Descripción
colocar() Se utiliza para establecer el valor.
conseguir() Se utiliza para obtener el valor actual.
conjunto perezoso() Finalmente se establece en el valor dado.
comparar y establecer Establece atómicamente el valor al valor actualizado dado si el valor actual == el valor esperado.

Operaciones atómicas

Aquellas operaciones que siempre se ejecutan juntas se conocen como operaciones atómicas o acción atómica . Todas las operaciones atómicas que se ejecutan efectivamente ocurren todas a la vez o no suceden en absoluto. Tres Los conceptos clave que están asociados con las acciones atómicas en Java son los siguientes:

1. La atomicidad se ocupa de qué acciones y conjuntos de acciones tienen invisible Por ejemplo, considere el siguiente fragmento de código:

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

En el código anterior, el comportamiento de ejecutar increment() y decrement() simultáneamente es indefinido y no predecible .

2. La visibilidad determina cuándo se puede aplicar el efecto de un hilo. visto por otra. Por ejemplo, considere el siguiente fragmento de código:

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

En el código anterior, es posible que el subproceso T2 nunca se detenga incluso después de que el subproceso T1 se establezca en verdadero. Además, no es que no haya sincronización entre subprocesos.

3. El orden determina cuándo las acciones en un hilo ocurren fuera de orden con respecto a otro hilo.

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

El orden en que aparecen los campos a y b en el hilo T2 puede diferir del orden en que se establecieron en el hilo T1.

Entendámoslo a través de un ejemplo.

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

En el fragmento de código anterior, hemos declarado una variable de tipo int contar y dentro del método incrementCount() lo asignó a 1. En tal caso, todo sucederá al mismo tiempo o no sucederá en absoluto. Por lo tanto, representa una operación atómica y la operación se conoce como atomicidad .

Consideremos otro fragmento de código.

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

Parece que también es una operación atómica pero no es así. Es una operación lineal que consta de tres operaciones, es decir, leer, modificar y escribir. Por tanto, puede ejecutarse parcialmente. Pero si utilizamos el código anterior en un entorno de subprocesos múltiples, crea un problema.

Supongamos que hemos llamado al código anterior en un entorno de un solo subproceso, el valor actualizado de count será 2. Si llamamos al método anterior mediante dos subprocesos separados, ambos acceden a la variable al mismo tiempo y también actualizan el valor de contar simultáneamente. Para evitar esta situación, utilizamos la operación atómica.

convención de nomenclatura de java

Java admite varios tipos de acciones atómicas, que son las siguientes:

  • Volátil variables
  • Operaciones atómicas de bajo nivel (inseguras)
  • clases atómicas

Veamos cómo podemos crear una operación atómica.

cadena dividida java

Variable atómica

La variable atómica nos permite realizar una operación atómica sobre una variable. Las variables atómicas minimizan la sincronización y ayudan a evitar errores de coherencia de la memoria. Por tanto, garantiza la sincronización.

El paquete atómico proporciona las siguientes cinco variables atómicas:

  • Entero atómico
  • atómicolargo
  • AtómicoBooleano
  • AtomicIntegerArray
  • AtómicoLongArray

La necesidad de una variable atómica

Consideremos el siguiente código.

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

El programa anterior proporciona el resultado esperado si se ejecuta en un entorno de subproceso único. Un entorno de subprocesos múltiples puede generar resultados inesperados. La razón detrás de esto es que cuando dos o más subprocesos intentan actualizar el valor al mismo tiempo, es posible que no se actualice correctamente.

Ofertas Java dos Soluciones para superar este problema:

  • Mediante el uso de bloqueo y sincronización
  • Usando variable atómica

Creemos un programa Java y usemos una variable atómica para superar el problema.

Usando variable atómica

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

Sincronizado vs. Atómico vs. Volátil

sincronizado Atómico Volátil
Se aplica sólo a los métodos. Se aplica sólo a variables. También se aplica solo a variables.
Garantiza visibilidad junto con atomicidad. También garantiza la visibilidad junto con la atomicidad. Garantiza visibilidad, no atomicidad.
No podemos lograr lo mismo. No podemos lograr lo mismo. Se almacena en RAM, por lo que el acceso a variables volátiles es rápido. Pero no proporciona seguridad ni sincronización para subprocesos.
Puede implementarse como un bloque sincronizado o un método sincronizado. No podemos lograr lo mismo. No podemos lograr lo mismo.
Puede bloquear el mismo objeto de clase o un objeto de clase diferente. No podemos lograr lo mismo. No podemos lograr lo mismo.