2011-08-02 20 views
27

Duplicar posible:
Java Synchronization¿Qué hace synchronized()/wait()/notifyAll() en Java?

estoy leyendo el libro partir Juegos Android.

Utiliza synchronized() mucho pero realmente no entiendo lo que hace. No he usado Java en mucho tiempo y no estoy seguro si alguna vez utilicé el multihilo.

En los ejemplos de Canvas usa synchronized(this). Sin embargo, en el ejemplo de OpenGL ES, crea un objeto llamado stateChanged y luego usa synchronized(stateChanged). Cuando el estado del juego cambia que llama stateChanged.wait() y luego stateChanged.notifyAll();

Algunos código:

Object stateChanged = new Object(); 

    //The onPause() looks like this: 
    public void onPause() 
     { 
      synchronized(stateChanged) 
      { 
       if(isFinishing()) 
        state = GLGameState.Finished; 
       else 
        state = GLGameState.Paused; 

       while(true) 
       { 
        try 
        { 
         stateChanged.wait(); 
         break; 
        } catch(InterruptedException e) 
        { 
        } 
       } 
      } 
     } 
//The onDrawSurface looks like this: 
public void onDrawFrame(GL10 gl) 
    { 
     GLGameState state = null; 
     synchronized(stateChanged) 
     { 
      state = this.state; 
     } 

     if(state == GLGameState.Running) 
     { 

     } 

     if(state == GLGameState.Paused) 
     { 
      synchronized(stateChanged) 
      { 
       this.state = GLGameState.Idle; 
       stateChanged.notifyAll(); 
      } 
     } 

     if(state == GLGameState.Finished) 
     { 
      synchronized(stateChanged) 
      { 
       this.state = GLGameState.Idle; 
       stateChanged.notifyAll(); 
      } 
     } 
    } 

//the onResume() looks like this: 
synchronized(stateChanged) 
     { 
      state = GLGameState.Running; 
      startTime = System.nanoTime(); 
     } 
+4

(En serio) ¿buscó algo en cualquier lugar antes de preguntar esto? Incluso buscar Stack Overflow? –

+1

Sí, lo hice ... @Joachim Sauver esa pregunta no cubre wait()/notify() –

+0

Acaba de agregar wait()/notify() - debe intentar formar la pregunta correctamente la primera vez en lugar de construyéndolo en vivo. –

Respuesta

29

This Java Tutorial probablemente puede ayudarle a entender lo usar sincronizado en un objeto sí lo hace.

Cuando se llama a object.wait(), liberará el bloqueo que se mantiene en ese objeto (lo que sucede cuando diga synchronized(object)) y congelará el hilo. El subproceso luego espera hasta que se llame a object.notify() o object.notifyAll() mediante un subproceso independiente. Una vez que se produce una de estas llamadas, permitirá que continúen los subprocesos que se detuvieron debido a object.wait(). Esto hace no significa que el hilo que llamó object.notify() o object.notifyAll() se congelará y pasará el control a un hilo de espera, simplemente significa que estos hilos de espera ahora pueden continuar, mientras que antes no lo eran.

+0

Eso tiene sentido ... así que al usar wait() detiene el hilo principal que va a pausar la aplicación y hace OpenGL ES stop. Luego, después de que se detiene OpenGL ES, el subproceso del procesador llama a notifyAll() que hace que el hilo principal termine pausando la aplicación –

1

sólo un hilo puede estar activa y bloque sincronizado por objeto dado dentro. llamadas espera detiene este derecho y desactiva el hilo actual hasta que alguien llame notify (all)() Luego el hilo inactivo comienza a querer volver a ejecutarse en el bloque sincronizado, pero se trata igual que todos los otros hilos que lo quieran. Solo uno elegido de alguna manera (el programador no puede influir ni depender de cuál) llega realmente allí.

4

Java (que se basa en Android) puede ejecutarse bajo múltiples subprocesos que pueden utilizar múltiples núcleos de CPU. Multi-threading significa que puede hacer que Java haga dos procesos en el mismo momento. Si tiene un bloque de código o método que necesita asegurarse de que solo puede ser operado por un hilo a la vez, sincroniza ese bloque de código.

Here is the official Java explanation from Oracle

Es importante saber que hay un procesador de costes/io involucrados con el uso sincronizado y sólo desea utilizarlo cuando lo necesite. También es importante investigar qué clases/métodos Java son seguros para subprocesos. Por ejemplo, no se garantiza que el operador de incremento ++ sea seguro para subprocesos, mientras que puede crear fácilmente un bloque de código sincronizado que incrementa un valor usando + = 1.

44

La palabra clave synchronized se usa para mantener variables o métodos -seguro. Si envuelve una variable en un bloque sincronizado, así:

synchronized(myVar) { 
    // Logic involing myVar 
} 

entonces cualquier intento de modificar el valor de miVar desde otro hilo, mientras que la lógica dentro del bloque sincronizado está en marcha va a esperar hasta que el bloque ha finalizado la ejecución. Asegura que el valor que va al bloque será el mismo durante el ciclo de vida de ese bloque.

+0

¿Es correcto decir que esta es la versión de Java de un Mutex? – Siavash

+1

@Siavash de .NET? Sí. –

1

La palabra clave sincronizada en java se utiliza para 2 cosas.

El primer significado es la denominada sección crítica, es decir, parte del código al que se puede acceder mediante un hilo simultáneamente. El objeto que pasa al synchronized permite algún tipo de denominación: si un código se ejecuta en synchronized(a) no puede acceder a otro bloque que está en synchronized(a) pero puede acceder al bloque de código en synchronized(b).

Otro problema es la comunicación entre hilos.El hilo puede esperar hasta que otro hilo lo notifique. Tanto la espera como la notificación deben escribirse en el bloque synchronized.

Era una descripción muy breve. Te sugiero que busques algún tutorial sobre multihilo y lo leas.

10

Cuando se utiliza de esta manera:

private synchronized void someMehtod() 

obtener estos efectos:

1. En primer lugar, no es posible que dos invocaciones de métodos sincronizados en el mismo objeto para intercalar. Cuando un hilo está ejecutando un método sincronizado para un objeto, todos los otros hilos que invocan métodos sincronizados para el mismo bloque de objetos (suspenden la ejecución) hasta que el primer hilo termina con el objeto.

2. En segundo lugar, cuando sale un método sincronizado, establece automáticamente una relación de pasar antes con cualquier invocación posterior de un método sincronizado para el mismo objeto. Esto garantiza que los cambios en el estado del objeto sean visibles para todos los hilos.

(Tomado de here)

usted consigue un efecto similar cuando se utiliza un bloque de código sincronizado:

private void someMethod() { 
    // some actions... 

    synchronized(this) { 
    // code here has synchronized access 
    } 

    // more actions... 
} 

Como se explica here

+0

Ok. ¿Qué pasa con los métodos wait() y notify()? Cómo interfieren en los hilos ... (He agregado un poco de mi código a la pregunta original) –

0

La palabra clave sincronizada, junto con las operaciones de espera y notificación forman un nonblocking condition monitor, una construcción útil para coordinar múltiples hilos.