2010-09-15 17 views

Respuesta

38

No, no significa eso. El "bloqueo de nivel de clase" es simplemente un bloqueo regular en un objeto diferente, es decir, SomeClass.class. El "bloqueo de nivel de objeto" se bloquea en this.

Editar: Sólo para asegurarse de que estoy siguiendo su comprensión de la terminología, se pregunta si m1 y m2 se pueden ejecutar al mismo tiempo, ya que se definen a continuación:

public class SomeClass { 
    public synchronized static void m1() { 
     //do something 
    } 

    public synchronized void m2() { 
     //do something 
    } 
} 

Y la respuesta es sí, m1 y m2 se pueden ejecutar al mismo tiempo. Es funcionalmente equivalente a esto:

public class SomeClass { 
    public static void m1() { 
     synchronized (SomeClass.class) { 
      //do something 
     } 
    } 
    public void m2() { 
     synchronized (this) { 
      //do something 
     } 
    } 
} 

Dado que se sincronizan en objetos completamente diferentes, no son mutuamente excluyentes.

+1

¿Qué pasa si ambos métodos son declarados estáticos? Creo que en ese caso, ambos se volverán mutuamente excluyentes, ¿es correcto? – buch11

+2

@ buch11: Es correcto, sería como si ambos estuvieran haciendo 'synchronized (SomeClass.class) {...}', y salvo cualquier escenario complejo de carga de clases, este será el mismo objeto en ambos casos. Técnicamente, la carga de clases le permite tener dos "cargas" separadas de la misma clase, y puede ejecutar métodos sincronizados estáticos en dichas clases diferentes en paralelo. Pero salvo que sea un caos, es mutuamente exclusivo. –

+0

Puede preguntarse qué sucede cuando se invoca un método estático sincronizado, ya que un método estático está asociado a una clase, no a un objeto. En este caso, el hilo adquiere el bloqueo intrínseco para el objeto Class asociado a la clase. ** Por lo tanto, el acceso a los campos estáticos de la clase está controlado por un bloqueo que es distinto del bloqueo para cualquier instancia de la clase. ** [Fuente] (https://docs.oracle.com/javase/tutorial/essential/concurrency /locksync.html) – Eduardo

6

en Java hay dos tipos de cerraduras:

  1. Nivel Clase
  2. Nivel Objeto

En el caso de los métodos estáticos de la cerradura siempre se comprueba la clase pero en caso de una instancia métodos el bloqueo siempre se comprueba en el objeto.

Ejemplo:

show1() es no estática y show() es estática. Ahora, show() se llama por nombre de clase (u objeto) y show1() se llama por objeto, luego ambos métodos pueden tener acceso a simultáneamente por dos hilos.

class Shared{ 
    static int x; 
    static synchronized void show(String s,int a){ 
     x=a; 
     System.out.println("Starting in method "+s+" "+x); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from method "+s+" "+x); 
    } 
    synchronized void show1(String s,int a){ 
     x=a; 
     System.out.println("Starting show1 "+s); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from show1 "+s); 
    } 
} 
class CustomThread extends Thread{ 
    Shared s; 
    public CustomThread(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     Shared.show(Thread.currentThread().getName(),10); 
    } 
} 
class CustomThread1 extends Thread{ 
    Shared s; 
    public CustomThread1(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     s.show1(Thread.currentThread().getName(),20); 
    } 
} 
public class RunSync { 
    public static void main(String[] args) { 
     Shared sh=new Shared(); 
     CustomThread t1=new CustomThread(sh,"one"); 
     CustomThread1 t2=new CustomThread1(sh,"two"); 
    } 
} 

de salida:

Starting in method one 10 
Starting show1 two 
Ending from method one 20 
Ending from show1 two   
12

bloqueo a nivel del objeto:

objeto de nivel de bloqueo es el mecanismo cuando se desea sincronizar un bloque de código método no estático o no estático de tal manera que sólo un hilo podrá ejecutar el bloque de código en una instancia determinada de la clase. Esto siempre se debe hacer para que el hilo de datos de nivel de instancia sea seguro. Esto se puede hacer de la siguiente manera: bloqueo a nivel

public class DemoClass 
{ 
    public synchronized void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (this) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
    private final Object lock = new Object(); 
    public void demoMethod(){ 
    synchronized (lock) 
{ 
    //other thread safe code 
} 
} 

Clase: bloqueo a nivel

Clase impide múltiples hilos para entrar en el bloque sincronizado en cualquiera de todas las instancias disponibles en tiempo de ejecución. Esto significa que si en tiempo de ejecución hay 100 instancias de DemoClass, solo un subproceso podrá ejecutar demoMethod() en cualquiera de las instancias a la vez, y todas las demás instancias estarán bloqueadas para otros subprocesos. Esto siempre se debe hacer para asegurar la seguridad de los hilos de datos estáticos.

public class DemoClass 
{ 
    public synchronized static void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (DemoClass.class) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
private final static Object lock = new Object(); 
public void demoMethod(){ 
synchronized (lock) 
    { 
    //other thread safe code 
    } 
} 
} 
2

ejemplo para entender bloqueos a nivel de clase de objeto y en Java

1) nivel de objeto de ejemplo de bloqueo

package com.test; 

public class Foo implements Runnable { 

    @Override 
    public void run() { 
     Lock(); 
    } 
    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(this) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

salida:

t1 
    t3 
    t2 
    in block t3 
    in block t1 
    in block t3 end 
    in block t1 end 
    in block t2 

Tenga en cuenta que t3 no se bloqueará cuando los hilos t1 y t2 bloqueen. Debido a que el bloqueo se coloca en este objeto y el hilo t3 tiene diferente este objeto que t1 hilo, t2 bloquear ejemplo

2) Nivel Clase

El código en la cerradura de nivel de objeto, solamente Foo.class es agregado en bloque sincronizado. Todos los hilos que se crean usando el objeto de la clase Foo serán bloqueados.

package com.test;  
public class Foo implements Runnable {   
    @Override 
    public void run() { 
     Lock(); 
    } 

    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(Foo.class) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

salida:

t1 
t3 
in block t1 
in block t1 end 
t2 
in block t3 
in block t3 end 
in block t2 
in block t2 end 

bloque sincronizado va a ser ejecutado por el mismo hilo.

0

Es posible que tanto el método sincronizado estático como el no estático puedan ejecutarse de forma simultánea o concurrente porque se bloquean en objetos diferentes.

Courtesy

1

bloqueo nivel de clase se consigue mediante la palabra clave "Static sincronizada, donde como nivel objetivo se consigue solamente por palabra clave sincronizada. Bloqueo nivel objeto se consigue para restringir mismo objeto para operar a través de hilo diferente, donde como se logra el bloqueo de nivel de clase para restringir cualquier objeto para que funcione.

0

Diferentes formas de bloqueo a nivel de clase: 1) DemoClass public class {

public static synchronized void demoMethod(){ 
    //dosomething 
} 

}

2)

clase pública DemoClass {

public void demoMethod(){ 

    synchronized(DemoClass.class){ 
     //dosomething 
    } 
} 

}

3)

public class {DemoClass

private final static Object lock = new Object(); 
public void demoMethod(){ 

    synchronized(lock){ 
     //dosomething 
    } 
} 

}

+0

¿Cómo responde esto la pregunta? – shmosel

0

bloqueo de nivel de clase e instancia de nivel de bloqueo de ambos son diferentes. Ambos no interfieren entre sí el estado de bloqueo. Si una instancia de una clase ya ha sido bloqueada por una secuencia, entonces otra cadena no puede obtener el bloqueo para esa instancia hasta que el primer enlace libere el bloqueo. El mismo comportamiento existe para el bloqueo de nivel de clase.

Pero si un hilo adquiere un bloqueo de nivel de clase, otro hilo puede adquirir el bloqueo en una de sus instancias. Ambos pueden trabajar parallel.`

package lock; 

class LockA implements Runnable { 
    @Override 
    public void run() { 
     synchronized (LockA.class) { 
      System.out.println("Class"); 
      try { 
       Thread.sleep(60 * 1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
public class TestClassVsInstanceLock { 
    public static void main(String[] args) { 
     final LockA a = new LockA(); 
     final LockA b = new LockA(); 
     try { 
      Thread t = new Thread(a); 
      Thread t1 = new Thread() { 
       @Override 
       public void run() { 
        synchronized (b) { 
         System.out.println("Instance 1"+ currentThread().currentThread().holdsLock(b)); 
         try { 
          Thread.sleep(10 * 1000); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }; 
      t.start(); 
      t1.start(); 
      synchronized (a) { 
       System.out.println("Instance2"); 
       Thread.sleep(10 * 1000); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

`

Esto imprimirá: - Instance2 Clase Instancia 1true

Todo se las publicarán al instante sin ningún tipo de pausa.

2

Si un hilo T1 ingresa a un método m1 obteniendo el bloqueo de nivel de clase, ¿significa esto que otro hilo T2 no puede ejecutar un método diferente m2 obteniendo el bloqueo de nivel de objeto?

Bloqueo de nivel de objeto y bloqueos de nivel de clase son diferentes. En el caso anterior, T2 puede ejecutar el método m2 obteniendo el bloqueo del nivel del objeto. Pero si m2 es static synchronized, T2 no puede invocar el método m2 a menos que T1 libere el bloqueo de nivel de clase en el método m1.

Object level lock:

No es posible que dos invocaciones de synchronized métodos en el mismo objeto para intercalar. Cuando un hilo está ejecutando un método synchronized para un objeto, todos los otros hilos que invocan los métodos synchronized para el mismo bloque de objetos (suspender la ejecución) hasta que el primer hilo se termine con el objeto.

Suponga que tiene dos synchronized m1 y m2 en métodos de objeto O. Si hilo T1 se encuentra en medio de la ejecución del método M1, luego pase T2 tiene que esperar para llamar al método m2 en el mismo objeto O a menos Cierre de liberación del hilo T1 en el método m1.

Class level lock:

Thread adquiere el bloqueo intrínseco para el objeto Class asociado con la clase. Por lo tanto, el acceso a los campos static de la clase está controlado por un bloqueo que es distinto del bloqueo para cualquier instancia de la clase.

Supongamos que el método m1 es static synchrnozed y el método m2 también es static synchronized y tiene dos objetos diferentes o1 y o2.

Si Thread T1 está en medio de la ejecución del método m1 en el objeto o1, entonces Thread T2 tiene que esperar para llamar al método m2 en el objeto o2 a menos que Thread T1 libere el bloqueo en el método m1.