2010-07-29 11 views
11

Cuando hablamos de bloqueo intrínseco nos referimos al objeto para el que pedimos la cerradura o para el método sincronizado?bloqueo intrínseco de hilo

El bloqueo está en el objeto o en su método de sincronización?

¡Estoy confundido!

Respuesta

4

métodos sincronizados bloquea el método en el objeto

synchronized void methodA() { 
    ....  
} 

es de alguna manera equivalente a

void methodA() { 
    synchronized (this) { 
     .... 
    } 
} 
+0

Cada objeto tiene un bloqueo intrínseco. Estas dos sentencias son equivalentes porque ambas se sincronizan en el bloqueo intrínseco del objeto que contiene el método A(). – Brandon

+0

Explicar las declaraciones sincronizadas a una persona que no entiende los métodos sincronizados no es una buena idea. Esto me confundió aún más. –

15

cerraduras intrínsecas son en el objeto:

class A 
{ 
    public synchronized void method1(){...} 
    public synchronized void method2(){...} 
} 

Si el hilo A está en method1 entonces threadB no puede ingresar a method2.

+1

Ojalá, Stackoverflow me permita +10 para su última línea. :) – UnKnown

1

El bloqueo es parte del objeto. Cada objeto tiene uno y puede ser bloqueado en dos formas:

  1. Utilizando el modificador synchronized en un método de instancia de la clase para bloquear el objeto asociado
  2. Uso de un bloque synchronized(object) {}

mismo modo, puede bloquear la Clase de un Objeto en lugar del Objeto mismo (bares mencionando por separado para comprender el modificador synchronized con un método static):

  1. Utilizando el modificador synchronized en un método estático de la clase para bloquear la Clase
  2. Uso de un bloque synchronized(clazz) {} donde clazz es la clase del objeto
9

En Java, un bloqueo intrínseco está implícito en cada uso de la palabra clave sincronizada

Cada uso de la palabra clave sincronizada se asocia con uno de los dos tipos de bloqueo intrínseco:

un "bloqueo de ejemplo", que se adjunta a un único objeto

un "bloqueo estático", que se adjunta a una clase

Si se declara un método como sincronizado, entonces se va a adquirir o bien la cerradura instancia o el bloqueo estático cuando se invoca, según sea un método de instancia o un método estático.

Los dos tipos de bloqueo tienen un comportamiento similar, pero son completamente independientes entre sí.

La adquisición del bloqueo de la instancia solo bloquea otros subprocesos para invocar un método de instancia sincronizado; no impide que otros subprocesos invoquen un método no sincronizado, ni les impide invocar un método sincronizado estático.

Del mismo modo, la adquisición del bloqueo estático solo bloquea otros hilos para invocar un método estático sincronizado; no impide que otros subprocesos invoquen un método no sincronizado, ni les impide invocar un método de instancia sincronizado.

Fuera de un encabezado de método, synchronized (this) adquiere el bloqueo de instancia.

El bloqueo estático pueden ser adquiridos fuera de una cabecera del método de dos maneras:

sincronizada (Blah.class), utilizando la clase literal

sincronizada (this.getClass()), si un objeto está disponible

0
private int count = 0; 
public synchronized void countFunc(){ 
     count++; 
    } 
Thread t1 = new Thread(new Runnable(){ 
      public void run(){ 
      for(int i=0;i<1000;i++){ 
       countFunc(); 
       }}}); 
     Thread t2 = new Thread(new Runnable(){ 
      public void run(){ 
      for(int i=0;i<1000;i++){ 
       countFunc(); 
      }}}); 

En el ejemplo anterior, tengo 2 hilos que intentan incrementar el valor del conteo. Y para evitar el entrelazado de hilos estoy tratando de agarrar un bloqueo intrínseco mediante el uso de sincronizado palabra clave.

conclusión, En este ejemplo, bloqueoes el bloque método countFunc con el sincronizado palabra clave y bloqueoesen la recuento variable. Espero que esto ayude

0

El bloqueo está en Objeto.

Tener un vistazo a la página tutorial de java en intrinsic locks

Cada objeto tiene un bloqueo intrínseco asociado a él. Por convención, un hilo que necesita acceso exclusivo y consistente a los campos de un objeto tiene que adquirir el bloqueo intrínseco del objeto antes de acceder a ellos, y luego liberar el bloqueo intrínseco cuando termina con ellos. Se dice que un hilo posee el bloqueo intrínseco entre el momento en que ha adquirido el bloqueo y liberado el bloqueo.

Mientras un hilo posee un bloqueo intrínseco, ningún otro hilo puede adquirir la misma cerradura. El otro hilo se bloqueará cuando intente adquirir el bloqueo.

dos formas de utilizar cerraduras intrínsecas:

  1. métodos sincronizados:

    Cuando un hilo invoca un método synchronized, adquiere automáticamente el bloqueo intrínseco para el objeto de que el método y lo libera cuando el método regresa.

    p. Ej.

    public synchronized void incrementCounter(){ 
        ++counter; 
    } 
    
  2. estados sincronizados

    diferencia de synchronized métodos, synchronized declaraciones deben especificar el objeto que proporciona el bloqueo intrínseco

    public int getCounter(){ 
        synchronized(this){ 
         return counter; 
        } 
    } 
    

    ejemplo completo:

    public class SynchronizedDemo{ 
    private int counter = 0; 
    
    public SynchronizedDemo(){ 
    
    } 
    public synchronized void incrementCounter(){ 
        ++counter; 
    } 
    public int getCounter(){ 
        synchronized(this){ 
         return counter; 
        } 
    } 
    public static void main(String[] args){ 
        SynchronizedDemo object = new SynchronizedDemo(); 
        for (int i=0; i < 5; i++){ 
         Thread t = new Thread(new SimpleRunnable(object)); 
         t.start(); 
        }   
    } 
    } 
    class SimpleRunnable implements Runnable{ 
    private SynchronizedDemo object; 
    
    public SimpleRunnable(SynchronizedDemo obj){ 
        this.object = obj; 
    } 
    public void run(){ 
        object.incrementCounter(); 
        System.out.println("Counter:"+object.getCounter()); 
    } 
    } 
    

Nota: Este ejemplo está escrito sólo para mostrar diferentes formas de utilizar las cerraduras intrínsecas. Usar AtomicInteger para la variable de contador es el enfoque correcto para este tipo de caso de uso.

Cuestiones relacionadas