Cómo sincronizar métodos utilizando las hebras java

Siempre que se trabaja en un programa Java que utiliza hilos, usted tiene que considerar el problema desagradable de concurrencia. En particular, ¿qué pasaría si dos subprocesos intentan acceder a un método de un objeto, precisamente en el mismo tiempo? A menos que se programa cuidadosamente, el resultado puede ser desastroso. Un método que realiza un cálculo simple devuelve resultados inexactos.

En una aplicación de banca en línea, usted podría descubrir que algunos depósitos se acreditan dos veces y algunos retiros no se acreditan en absoluto. En un sistema de pedidos en línea, la orden de un cliente podría obtener registrada en la cuenta de un cliente diferente.

La clave para manejar los problemas de concurrencia es el reconocimiento de que los métodos de actualización de datos y que podría ser llamado por más de un hilo. Después de identificar esos métodos, la solución es simple. Que acaba de añadir la sincronizada palabra clave para la declaración de método, de esta manera:

pública sincronizado algunMetodo vacío () ...

Este código indica a Java para colocar una bloquear en el objeto de manera que no hay otros métodos pueden llamar a cualquier otro métodos sincronizados para el objeto hasta que este método termina. En otras palabras, se desactiva temporalmente multihilo para el objeto.

He aquí algunos ejemplos concretos. Este código crea una instancia de la CountdownClock clase.

DoTwoThings clase importación java.util.concurrent.ScheduledThreadPoolExecutor-públicas {piscina ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor (2) -CountDownClock reloj = new CountdownClock (20) -públicos static void main (String [] args) {nuevos DoTwoThings (-)} (DoTwoThings ) {pool.execute (reloj) -pool.execute (reloj) -pool.shutdown () -}}

La salida resultante es una mezcla heterogénea impredecible de salidas de dos hilos, con algunos de los recuentos de duplicado y otros omiten por completo, como este:

T menos 20T menos 20T menos 19T menos 19T menos 18T menos 17T menos 16T menos 15T menos 13T menos 13T menos 12T menos 12T menos 11T menos 11T menos 10T menos 9T menos 7T menos 7T menos 6T menos 5T menos 4T menos 3T menos 2T menos 2T menos 1T menos 0

Los dos hilos ejecutan sus bucles simultáneamente, así que después de un hilo muestra su T menos 20, el otro hilo muestra su propio T menos 20. Lo mismo sucede para T menos 19, T menos 18, y así.

Video: Sincronización De Hilos ... método join() en Java

A continuación, este código genera dos hilos, cada uno de los cuales se ejecuta una copia de la CountdownClock El código de ejemplo.

clase de importación java.util.concurrent.ScheduledThreadPoolExecutor pública DoTwoThingsSync {piscina ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor (2) -CountDownClockSync reloj = new CountDownClockSync (20) -públicos static void main (String [] args) {nueva DoTwoThingsSync () - DoTwoThingsSync} ( ) {pool.execute (reloj) -pool.execute (reloj) -pool.shutdown () -}}

Java sincronizada palabra clave asegura que sólo un hilo a la vez llama al correr método. La salida resultante muestra una ejecución completa de la correr método seguido por otro.

CountDownClockSync clase extends Thread {private int puesta en CountDownClockSync pública (inicio int) {} this.start = arranque sincronizado public void run () {for (int t = t puesta en gt; = 0- t -) {System.out.println ("T menos " + T) -probar {Thread.sleep (1000) -} catch (InterruptedException e) {}}}}

llamadas de los dos hilos a la correr método no se entrelazan, por lo que los conteos de salida por debajo de 20 a 0 y luego una cuenta regresiva por segunda vez desde 20 a 0:

T menos 20T 19T minus menos 18

Y así sucesivamente, hasta llegar

T menos 2T 1T menos, menos, menos 0T 20T 19T menos -18

Y así sucesivamente, hasta llegar

T menos 2T 1T menos, menos 0

La parte difícil es saber qué métodos para sincronizar. Cualquier método que actualiza las variables de instancia está en riesgo - y necesita ser sincronizado. Eso es porque cuando dos o más hilos corren un método, al mismo tiempo, los hilos tienen una copia común de las variables de instancia del método.

Incluso los métodos que consisten en una sola línea de código están en riesgo. Considere este método:

int sequenceNumber = 0-public int getNextSequenceNumber () {return sequenceNumber ++ -}

Se podría pensar que ya que este método tiene sólo una declaración, algún otro flujo no podía interrumpirlo en el medio. Por desgracia, ese no es el caso. Este método debe obtener el valor de la secuencia de números campo, añadir 1 a ella, salvo el valor actualizado de nuevo a la secuencia de números campo, y devuelve el valor.

De hecho, esta declaración única de Java compila a 11 instrucciones de código de bytes. Si el hilo se adelantó entre cualquiera de los códigos de bytes por otro subproceso a llamar al mismo método, los números de serie consiguen munged.

Por motivos de seguridad, ¿por qué no hacer que todos los métodos sincronizados? Usted tiene dos razones para no hacerlo:

Video: Curso Java. Threads I. Programación de hilos. Vídeo 168

  • La sincronización de los métodos requiere tiempo. Java tiene que adquirir un bloqueo en el objeto que se está sincronizado, ejecute el método, y luego liberar el bloqueo. Pero antes de que pueda hacer eso, tiene que comprobar para asegurarse de que algún otro flujo no tiene ya un bloqueo en el objeto. Todo este trabajo lleva tiempo.

  • Más importante aún, la sincronización de todos sus métodos contra del propósito de múltiples hilos, por lo que debe sincronizar sólo aquellos métodos que lo requieran.

los sincronizada palabra clave no bloquea todo el acceso a un objeto. Otros hilos todavía pueden ejecutar los métodos de la falta de sincronización del objeto mientras que el objeto está bloqueado.

los Objeto clase proporciona tres métodos que pueden dejar objetos sincronizados coordinan sus actividades. los Espere Método pone un hilo en el estado de espera hasta que algún otro subproceso llama ya sea el objeto de notificar o (más comúnmente) notifyAll método. Estos métodos son útiles cuando un hilo tiene que esperar a que otro hilo que hacer algo antes de que pueda proceder.

El ejemplo clásico es un sistema bancario en el que un hilo hace retiros y el otro hace que los depósitos. Si el balance de la cuenta de un cliente llega a cero, el hilo que hace retiros pueden llamar Espere- a continuación, el hilo que hace que los depósitos pueden llamar notifyAll. De esta manera, cada vez que se realiza un depósito, el hilo de la retirada puede volver a comprobar saldo de la cuenta del cliente para ver si ahora tiene suficiente dinero.

Artículos Relacionados