Pregunta

Esta pregunta ya tiene una respuesta aquí:

¿Cuál es la diferencia entre un método sincronizado y un bloque sincronizado en Java?

He estado buscando la respuesta en la red, la gente parece estar tan insegura de este :-(

Mi opinión sería que no hay diferencia entre los dos, excepto que el bloque de sincronización podría tener un alcance más localizado y, por lo tanto, el bloqueo será de menor tiempo.

Y en caso de bloqueo en un método estático, ¿en qué se toma el bloqueo? ¿Cuál es el significado de un bloqueo en clase?

¿Fue útil?

Solución

Un método sincronizado utiliza el receptor del método como bloqueo (es decir this para métodos no estáticos, y la clase de encierra para métodos estáticos). Synchronized Blocks usa la expresión como bloqueo.

Entonces, los siguientes dos métodos son equivalentes desde el bloqueo de la prospectiva:

synchronized void mymethod() { ... }

void mymethod() {
  synchronized (this) { ... }
}

Para métodos estáticos, la clase se bloqueará:

class MyClass {
  synchronized static mystatic() { ... }

  static mystaticeq() {
    syncrhonized (MyClass.class) { ... }
  }
}

Para bloques sincronizados, puede usar cualquier nonull objeto como bloqueo:

synchronized (mymap) {
  mymap.put(..., ...);
}

Alcance de bloqueo

Para los métodos sincronizados, el bloqueo se llevará a cabo en todo el alcance del método, mientras que en el synchronized Bloque, el bloqueo se mantiene solo durante ese alcance del bloque (también conocido como sección crítica). En la práctica, el JVM puede optimizar eliminando algunas operaciones de la synchronized Bloquee la ejecución si puede demostrar que se puede hacer de manera segura.

Otros consejos

Un método sincronizado es la taquigrafía. Este:

class Something {
    public synchronized void doSomething() {
        ...
    }

    public static synchronized void doSomethingStatic() {
        ...
    }
}

es, para todos los efectos, es equivalente a esto:

class Something {
    public void doSomething() {
        synchronized(this) {
            ...
        }
    }

    public static void doSomethingStatic() {
        synchronized(Something.class) {
            ...
        }
    }
}

(Dónde Something.class es el objeto de clase para la clase Something.)

Entonces, de hecho, con un bloque sincronizado, puede ser más específico sobre su bloqueo y más de grano fino sobre cuándo desea usarlo, pero aparte de eso no hay diferencia.

Sí, esa es una diferencia. El otro es que puedes adquirir un bloqueo en otros objetos que this.

La diferencia clave es esta: si declara que se sincronizará un método, entonces todo el cuerpo del método se sincroniza; Sin embargo, si usa el bloque sincronizado, entonces puede rodear solo la "sección crítica" del método en el bloque sincronizado, mientras deja el resto del método fuera del bloque.

Si todo el método es parte de la sección crítica, entonces efectivamente no hay diferencia. Si ese no es el caso, entonces debe usar un bloque sincronizado alrededor de la sección crítica. Cuantas más declaraciones tenga en un bloque sincronizado, menos paralelismo general obtendrá, por lo que desea mantenerlas al mínimo.

Un método sincronizado se bloquea en la instancia de objeto en el que está contenido.

Donde como un bloque sincronizado puede bloquear en cualquier objeto, típicamente un obecto mutex definido como una variable de instancia. Esto permite un mayor control sobre qué bloqueos están en funcionamiento.

Mi opinión sería que no hay diferencia entre los dos, excepto que el bloque de sincronización podría tener un alcance más localizado y, por lo tanto, el bloqueo será de menor tiempo.

Sí. Tienes razón. A diferencia de synchronized Los métodos, las declaraciones sincronizadas deben especificar el objeto que proporciona el bloqueo intrínseco.

Ejemplo del tutorial Java:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

Las declaraciones sincronizadas también son útiles para mejorar la concurrencia con sincronización de grano fino. Puede encontrar un buen ejemplo en la misma página de tutorial para el siguiente caso de uso.

Supongamos, por ejemplo, clase MsLunch tiene dos campos de instancia, C1 y C2, que nunca se usan juntos. Todas las actualizaciones de estos campos deben ser synchronized, pero no hay razón para evitar que una actualización de C1 se entrelaze con una actualización de C2, y hacerlo reduce la concurrencia al crear un bloqueo innecesario. En lugar de usar métodos sincronizados o usar el bloqueo asociado con esto, creamos dos objetos únicamente para proporcionar bloqueos.

Y en caso de bloqueo en un método estático, ¿en qué se toma el bloqueo? ¿Cuál es el significado de un bloqueo en clase?

En este caso, el hilo adquiere el bloqueo intrínseco para el objeto de clase asociado con la clase. Por lo tanto, el acceso a los campos estáticos de la clase está controlado por un bloqueo distinto del bloqueo para cualquier caso de la clase.

Cuando haces un método como sincronizado (no static ) :

No es posible para dos invocaciones de synchronized Métodos en el mismo objeto para entrelazar. Cuando un hilo está ejecutando un método sincronizado para un objeto, todos los demás hilos que invocan métodos sincronizados para el mismo bloque de objeto (suspender la ejecución) hasta que el primer hilo se realice con el objeto.

Si haces un método como static synchronized :

No es posible para dos invocaciones de static synchronized Métodos en diferentes objetos de la misma clase para entrelazar. Cuando un hilo está ejecutando un static synchronized Método para un objeto de la clase A, todos los demás hilos que invocan static synchronized Métodos en cualquiera de los objetos del bloque de clase A (suspender la ejecución) hasta que el primer subproceso se realice con la ejecución del método.

Encuentra mejores alternativas a la sincronización en esta pregunta de SE:

¿Evitar sincronizado (esto) en Java?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top