2011-01-03 10 views
19

Me pregunto cómo funciona exactamente "sincronizado" en Java.¿Qué hace exactamente "sincronizado"? Bloquear una función o bloquear una función de objetos?

Digamos que modelo un juego de tablero que consiste en una serie de campos. Implemento los campos como una clase (Campo) y el tablero como una clase (Tablero) que contiene un número de campos. Digamos además que modelé un método moveTo (Player pl) en Field, para que un jugador se mueva a ese campo. Cada jugador está representado por un hilo.

Aunque todos los hilos deben realizar algunas acciones simultáneamente (por ejemplo, rodando sus dados), solo debe haber un jugador que se mueva a la vez.

¿Cómo me aseguraré de eso? ¿Es suficiente sincronizar el método moveTo (Player pl)? ¿O necesitaría un método en cascada en el tablero para asegurarme de que solo un jugador se mueve a la vez? (¿O hay una mejor solución)?

Para llevarlo a la línea de fondo:
que "sincronizado" bloquear un método en el que cada objeto tiene este método o sería sincronizado bloquear un único método en el objeto que está actualmente en uso?
Y si es el segundo: ¿hay alguna manera fácil de bloquear un método para cada objeto que tiene implementado este método?

Gracias!

+5

'synchronized' nunca bloquea una función, punto. Solo ** puedes ** bloquear ** un * objeto *. Con un método de instancia, es 'esto'. Con un método estático, es el objeto de clase en el que se define el método (MyClass.class). –

+0

solo porque preguntaste por qué necesito multihilo: de hecho estoy implementando algún tipo de juego multiusuario "pacman" como una tarea. Cada jugador y cada fantasma debe ser un hilo. Sin embargo, debo verificar si un jugador golpea a un fantasma o viceversa después de cada paso. En este punto, a veces recibo excepciones que me dicen algo así como "Ghost-A quería eliminar Player-B del campo-XY, pero Player-B ya no estaba allí". Creo que este error proviene del hecho de que los movimientos de los hilos no estaban sincronizados. – speendo

+0

La sincronización sería una solución a este problema. Pero no el único. – Falmarri

Respuesta

27

Lo que pienso que usted quiere es la siguiente:

class Field { 

    // instance of the board 
    private Board board; 

    public void moveTo(Player p){ 
     synchronized (board) { 
      // move code goes here 
     } 
    } 
} 

Esto hará que sea para que por tabla, sólo un jugador se mueve a la vez. Si obtiene el bloqueo de sincronización en la placa, solo un campo puede ingresar al bloqueo sincronizado a la vez. (Asumiendo una tabla)

Si simplemente escribió:

public synchronized void moveTo(Player p){ 

sólo sería asegurar que los jugadores no podían moverse al mismo campo a la vez. Esto se debe a que cuando se escribe un método con sincronización en la definición, se bloqueará en el nivel del objeto. Entonces, cada instancia de Field será su propio objeto de bloqueo, y por lo tanto, los jugadores podrían moverse al mismo tiempo siempre y cuando no se muevan al mismo Campo.

+0

yay gracias! Creo que lo entiendo ahora :) – speendo

+1

@Marcel, me alegra poder ayudar. – jjnguy

+0

Muy buena regla general: ¡No sincronizar/bloquear objetos no finales! – Voo

1

La sincronización bloquea el acceso a un recurso. Ese recurso puede ser una función o un objeto (incluido el objeto this).

No podemos darle consejos específicos sin un ejemplo específico.

En su ejemplo, si los jugadores solo pueden tomar 1 turno a la vez, ¿por qué necesitan estar en sus propios hilos? ¿Por qué necesitan tirar sus dados al mismo tiempo?

sincronizar una función bloquea las llamadas a la versión de esa instancia de ese método (a menos que sea un método estático).

And if the second is the case: is there an easy way to lock a function for every object that has this function implemented?

Esto parece sugerir que su diseño podría ser reevaluada. ¿Los métodos de instancia de su objeto realmente comparten estado de modo que necesitan que sus métodos se sincronicen entre sí? ¿Por qué?

6

sincronizado bloquea un objeto, no un método. Java no tiene funciones.

Si desea que un método sea llamado una sola vez en todos los objetos, puede bloquearlo en un objeto compartido, como la clase.

Sugeriría que solo necesitas un hilo para realizar todos los movimientos/operaciones y esto simplificaría el código significativamente. ¿Por qué tiene que ser de subprocesos múltiples?

+1

La sincronización en el objeto de clase podría tener algunos problemas involuntarios si también hay métodos estáticos sincronizados. Si está tratando de sincronizar una sección crítica específica, cree y sincronice en un objeto de bloqueo específicamente para ello, como 'private static final Object methodAMutex = new Object()'. O use las primitivas de concurrencia agregadas en 6. –

+0

Por supuesto, sería estúpido bloquear una función en un lenguaje orientado a objetos ... ¡Gracias, no pensé en esto antes! – speendo

+2

@Marcel: Bueno. Eso depende. En Python puede bloquear funciones, pero eso es una consecuencia de que las funciones son objetos. – Falmarri

1

Depende de dónde se use.

Si se utiliza en un método típico, agarra exclusivamente el objeto "bloqueo" del objeto en cuestión. Ningún otro subproceso puede procesar métodos en ese objeto si necesitan acceso exclusivo al objeto "bloquear" del mismo objeto (los métodos no sincronizados no requieren acceso exclusivo al bloqueo).

Si se utiliza en un método estático, atrapa exclusivamente el objeto de bloqueo del Objeto que representa la Clase. Ningún otro subproceso puede procesar métodos en ese objeto de clase si necesitan acceso exclusivo al objeto de "bloqueo" del mismo objeto de clase (los métodos no sincronizados no requieren acceso exclusivo al bloqueo).

Si se utiliza con un objeto explícitamente establecido, atrapa exclusivamente el objeto de bloqueo del objeto explícitamente indicado. Nuevamente, ningún otro Thread puede agarrar exclusivamente el bloqueo de ese objeto durante ese tiempo.

Una vez que abandona el alcance de un bloque sincronizado, renuncia a su bloqueo exclusivo en el bloqueo.

+2

gran Avatar, por cierto, ¿es del juego de la vida? – speendo

Cuestiones relacionadas