2011-03-30 14 views
9

Si tengo un método público sincronizado y un método privado:métodos sincronizados

public synchronized void doSomething() { 
    doSomethingElse() 
} 

private void doSomethingElse() { 
} 

¿Es necesario sincronizar el método privado?

+2

Depende de lo que quiere que hagan, y si se les debe permitir que se ejecuten al mismo tiempo. –

Respuesta

1

Cualquier método llamado desde un método sincronizado (o desde dentro de un bloque synchronized) se ejecuta mientras está sincronizado. No necesita sincronizar por separado el método privado si solo se llama desde métodos sincronizados.

4

NO: si se llama a la única forma en que se llama a doSomethingElse() mediante otro método que está sincronizado.

Posiblemente sí: Si llama doSomethingElse() de alguna otra manera, a través de un método que no está sincronizada, y hay que protegerla contra el acceso concurrente.

0

Si sincroniza un bloque de código, todo lo que se llame desde ese bloque de código (en el mismo subproceso) aún conserva el bloqueo inicial. Por lo tanto, doSomethingElse sigue siendo una parte del bloque sincronizado cuando se llama desde doSomething.

Si lo hizo:

public synchronized void doSomething() { 
    new Thread() { 
    public void run() { 
     doSomethingElse(); 
    } 
    }.start(); 
} 
private void doSomethingElse() { 
} 

Entonces doSomethingElse haría no tener la cerradura que fue adquirida por doSomething.

También evite los métodos sincronizados ya que expone los detalles de implementación de su política de simultaneidad. Ver esta pregunta en (este)/métodos sincronizados sincronizados: Avoid synchronized(this) in Java?

Si doSomethingElse se debe sincronizar, independientemente de si es o no es llamado desde doSomething, no vendría mal para sincronizar doSomethingElse como se bloqueos sincronizados re-entrante (es decir, si un hilo ya tiene un bloqueo en un objeto, puede volver a obtener el bloqueo).

0

Personalmente, no me gustan los métodos sincronizados. Yo prefiero para sincronizar con algún tipo de bloqueo varaible, como tan:

private final Object lock = new Object(); 

public void doSomething() { 
    synchronized(lock) { 
    // Do some safely 
    doSomethingElse(); 
    } 
    // Do some work un-safely 
} 

private void doSomethingElse() { 
    // Do some work safely because still in lock above 
    // ... 
} 
5

Depende de lo que está haciendo. ¿Necesita garantizar el acceso en serie al doSomethingElse()?

Si es así, y lo único que llama a doSomethingElse() es , entonces no, no necesita sincronizar. Pero si algún otro método puede llamar al doSomethingElse(), entonces sí, debe sincronizarlo también.

13

Depende:

  • doSomethingElse Si es seguro llamar al mismo tiempo, entonces no es necesario synchronized.
  • Si no es así, entonces la respuesta depende de donde recibe el nombre de:
    • Si sólo se conoce de otros métodos synchronized, entonces no tiene por qué ser synchronized (pero marcándolo como tal voluntad no hacer daño);
    • Si se puede invocar desde métodos que no son synchronized ellos mismos, entonces debe ser synchronized.
0

A pesar de lo que ha hecho está bien, en mi opinión, la sincronización se debe hacer en la granularidad más bajo posible. Lo que sugeriría sincronizar la función privada real. Actualmente, asumes que ninguna otra función en la clase llamará a la función privada de forma independiente. Este puede no ser el caso en el futuro.

2

Esta es la intención de la anotación @GuardedBy. Si espera que una necesidad bloqueo llevará a cabo cuando se llama a este método, anotar que con eso y el nombre de la cerradura (en el ejemplo sería:

@GuardedBy("this") private void doSomethingElse() {…} 

entonces usted puede comprobar que el invariante es cierto con FindBugs.

también puede utilizar el other net.jcip.annotations para describir el hilo de seguridad o falta de ella y tienen FindBugs validar estos supuestos también. por supuesto, the book necesita un enchufe así.

0

a pesar de que el código funciona correctamente cuando el método privado no está sincronizado Hronized, parece prudente desde una perspectiva de mantenimiento mantener sincronizado el método privado.

Los bloqueos intrínsecos son reentrantes, no hay ningún problema al agregar la palabra clave sincronizada al método privado.

Poner el código en un método privado invita a llamarlo por otros métodos, por lo que sería lógico sincronizar el método privado en el caso de que en el futuro se llame desde otro método que de otro modo no necesita ser sincronizado.

Cuestiones relacionadas