Debe introducir al menos 3 caracteres en el buscador.
Inicio / Wikis / Cursos gratis / Java partiendo de Cero - Sincronicemos los relojes

Java partiendo de Cero - Sincronicemos los relojes

 ****- (59 opiniones)
Copyright Curso gratis de Jorge Bourdette - 26 de Agosto de 2005
Temas Relacionados: JavaProgramación web
66. Sincronicemos los relojes
Un problema básico del multithreading es cuando varios programas (o, para el caso, varios threads) acceden a los mismos datos: ¿cómo sabemos si uno de ellos no los modifica mientras los está usando otro?.

Veamos un ejemplo, donde suponemos que varios threads usan la variable valorImportante:


if (valorImportante > 0 ) {

..... algo se procesa acá ........

valorImportante = valorImportante - 1;

..... sigue.....................

}

¿Cómo nos aseguramos que valorImportante no cambió entre el if y la línea resaltada? Otros threads pueden haberlo modificado mientras tanto. Asimismo, puede suceder que dos threads estén ejecutando la misma porción de código, y se pierda uno de los decrementos. Imaginen algo así:

(antes) valorImportante = 10

(thread 1) lee valorImportante = 10

(thread 2) lee valorImportante = 10

(thread 1) 10 -1 = 9

(thread 2) 10 -1 = 9

(thread 2) asigna 9 a valorImportante

(thread 1) asigna 9 a valorImportante

(después) valorImportante = 9

Como vemos, a pesar de haber restado dos veces, hemos perdido una de las restas. Aunque usemos -= en vez de la resta es lo mismo, porque el código igualmente se resuelve en varios pasos (varias operaciones atómicas).

Para evitar esto, Java nos brinda la palabra clave Synchronized, que bloquea el acceso a una variable a todos los threads menos el que lo está usando.

Vamos a ver un caso específico; se trata de dos contadores que usan el mismo sumador para sumar de a uno una cantidad a. Supuestamente entre los dos deben llevar el sumador (a) hasta 20000.


Archivo Ejemplo22.java, compilar con javac Ejemplo22.java, ejecutar con java Ejemplo22

public class Ejemplo22 {

public static void main(String argv[]) {

Sumador A = new Sumador(); un único sumador

Contador C1 = new Contador(A); dos threads que lo usan...

Contador C2 = new Contador(A); ...para sumar

C1.start();

C2.start();

try {

C1.join();

C2.join();

}

catch (Exception e) {

System.out.println(e);

}

}

}

class Contador extends Thread {

Sumador s;

Contador (Sumador sumador) {

s = sumador; le asigno un sumador a usar

}

public void run() {

s.sumar(); ejecuto la suma

}

}

class Sumador {

int a = 0;

public void sumar() {

for (int i=0; i<10000; i++ ) {

if ( (i % 5000)
0 ) { "%" da el resto de la división:

System.out.println(a); imprimo cada 5000

}

a += 1;

}

System.out.println(a); imprimo el final

}

}

Ejecutando esto nos da más o menos así (cada corrida es diferente, dependiendo de cómo se "chocan" los threads y la carga de la CPU):


C:\java\curso>java Ejemplo22

0

87

8926

10434

14159

17855

Esto se debe justamente a lo que explicábamos al principio: a veces los dos threads intentan ejecutar a += 1 simultáneamente, con lo que algunos incrementos se pierden.

Podemos solucionar esto modificando el método run():


public void run() {

synchronized (s) {

s.sumar();

}

}

Con esto, sólo a uno de los dos threads se les permite ejecutar s.sumar() por vez, y se evita el problema. Por supuesto, el otro thread queda esperando, por lo que más vale no utilizar esto con métodos muy largos ya que el programa se puede poner lento o aún bloquearse.

La salida ahora será:


C:\java\curso>java Ejemplo22

0 <

5000 < primer thread

10000 <

10000 (

15000 ( segundo thread

20000 (

Lo mismo logramos (y en forma más correcta) declarando como synchronized al método sumar():

public synchronized void sumar() { .............

Esto es mejor porque la clase que llama a sumar() no necesita saber que tiene que sincronizar el objeto antes de llamar al método, y si otros objetos (en otros threads) lo llaman, no necesitamos preocuparnos.
Tabla de contenidos
  1. 1 - JAVA DESDE CERO
  2. 2 - Qué es Java
  3. 3 - Lenguaje de Objetos
  4. 4 - Independiente de la plataforma
  5. 5 - Algunas características
  6. 6 - El Java Development Kit
  7. 7 - EMPECEMOS DE UNA VEZ!
  8. 8 - Javascript
  9. 9 - Al fin. Java!
  10. 10 - LAS CLASES EN JAVA
  11. 11 - Estructura de una clase
  12. 12 - ESTRUCTURA DE CLASES
  13. 13 - Declaración de la clase
  14. 14 - El cuerpo de la clase
  15. 15 - EL CUERPO DE LOS MÉTODOS
  16. 16 - Declaración de variables locales
  17. 17 - Asignaciones a variables
  18. 18 - Operaciones matematicas
  19. 19 - Llamadas a métodos
  20. 20 - LAS ESTRUCTURAS DE CONTROL
  21. 21 - if.[else]
  22. 22 - Switch.case.brake.default
  23. 23 - While
  24. 24 - Do.while
  25. 25 - For
  26. 26 - Break y continue
  27. 27 - Otras...
  28. 28 - HAGAMOS ALGO...
  29. 29 - La clase Complejo
  30. 30 - Algo sobre los métodos
  31. 31 - JAVA A TRAVÉS DE LA VENTANA
  32. 32 - Nuestra primera ventana
  33. 33 - Un poco de detalle
  34. 34 - Y los eventos...
  35. 35 - UNA VENTANA CON VIDA
  36. 36 - Viajando con Java
  37. 37 - Preparando listas
  1. 38 - Agregando fechas
  2. 39 - Juntando todo hasta aquí
  3. 40 - COMPLETANDO LA VENTANA
  4. 41 - Un poquito de actividad
  5. 42 - Y para terminar...
  6. 43 - Finale con tutto
  7. 44 - UN PARÉNTESIS DE ENTRADA/SALIDA
  8. 45 - Primera Lectura
  9. 46 - Capturando excepciones
  10. 47 - Los applets y los archivos
  11. 48 - Nuestro modesto "Editor"
  12. 49 - VOLVIENDO AL AWT
  13. 50 - Menú a la Java
  14. 51 - Dialogos
  15. 52 - DIBUJAVA
  16. 53 - Canvas en acción
  17. 54 - El applet-container
  18. 55 - Nuestro Canvas a medida
  19. 56 - DIBUJAVA II
  20. 57 - Vectores en acción
  21. 58 - Flicker molesto!
  22. 59 - Anímate!
  23. 60 - JAVA EN HEBRAS
  24. 61 - Los pasos basicos
  25. 62 - Reunión de amigos
  26. 63 - Creando Threads
  27. 64 - Y los applets...?
  28. 65 - LA LIEBRE Y LA TORTUGA (Y EL GUEPARDO)
  29. 66 - Sincronicemos los relojes
  30. 67 - Mas sincronización
  31. 68 - MULTIMEDIA!
  32. 69 - Parametrizando un applet
  33. 70 - PASEANDO POR LA RED
  34. 71 - Los Sockets
  35. 72 - Un servidor atento
  36. 73 - El cliente satisfecho
Autor y licencia de 'Java partiendo de Cero - Sincronicemos los relojes'
Jorge Bourdette Extraído de: http://www.publispain.com/supertutoriales Copyright
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.

Wikis relacionados con 'Java partiendo de Cero - Sincronicemos los relojes'

Amplio tutorial de Java para empezar a trabajar y ampliar conocimientos de este lenguaje.
En el mundo de los Incas, Mayas y Aztecas, el tiempo no es concebido proceder... Más »
Partiendo del cine mudo como documento histórico y subrayando el valor artístico de la música... Más »
Partiendo de la idea de que un cambio en la mentalidad mundial incide directamente en... Más »
El trabajo que sometemos a su consideración pretende mostrar nuestras consideraciones teóricas y metodológicas... Más »
¿Estás seguro de que deseas eliminar este capítulo?