Pregunta

¿Alguien puede decirme la ventaja del método sincronizado sobre el bloque sincronizado con un ejemplo?

¿Fue útil?

Solución

  

¿Puede alguien decirme la ventaja del método sincronizado sobre el bloque sincronizado con un ejemplo? Gracias.

No hay una clara ventaja de usar método sincronizado sobre el bloque.

Tal vez el único (pero yo no diría que es una ventaja) es que no es necesario incluir el this referencia de objeto.

Método:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Bloquear:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

Vea? Ninguna ventaja en absoluto.

Los bloques hacer tienen ventajas sobre los métodos, sin embargo, sobre todo en la flexibilidad porque se puede utilizar como otro objeto de bloqueo, mientras que la sincronización del método encerraría todo el objeto.

Comparación:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

vs.

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Además, si el método crece todavía se puede mantener a la sección separada sincronizada:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}

Otros consejos

La única diferencia real es que un bloque sincronizado puede elegir qué objeto se sincroniza sucesivamente. Un método sincronizado sólo puede utilizar 'this' (o la instancia de clase correspondiente para un método de clase sincronizado). Por ejemplo, estos son semánticamente equivalentes:

synchronized void foo() {
  ...
}

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

Este último es más flexible ya que puede competir por el bloqueo asociado de cualquier objeto, a menudo una variable miembro. También es más granular, ya que podría tener el código concurrente ejecutar antes y después del bloque pero aún dentro del método. Por supuesto, es posible que utilices la misma facilidad un método sincronizado por refactorización el código concurrente en métodos no sincronizados separados. Utilice el que hace que el código sea más comprensible.

sincronizada Método

Pros:

  • El IDE puede indicar los métodos sincronizados.
  • La sintaxis es más compacto.
  • Fuerzas para dividir los bloques sincronizados con los métodos separados.

Contras:

  • Sincroniza a esto y por lo que hace posible a los de afuera se sincronice con él también.
  • Es más difícil mover el código fuera del bloque sincronizado.

bloque sincronizado

Pros:

  • Permite el uso de una variable privada para el bloqueo y así forzar la cerradura para permanecer dentro de la clase.
  • bloques sincronizados pueden ser encontrados buscando referencias a la variable.

Contras:

  • La sintaxis es más complicado y por lo que hace que el código sea más difícil de leer.

En lo personal prefiero utilizar métodos sincronizados con clases enfocadas únicamente a la necesidad de que la sincronización. Tal clase debe ser tan pequeño como sea posible y por lo que debe ser fácil de revisar la sincronización. Otros no deberían tener que preocuparse acerca de la sincronización.

La diferencia principal es que si se utiliza un bloque sincronizado puede bloquear en un objeto que no sea este que permite ser mucho más flexible.

Suponga que tiene una cola de mensajes y múltiples productores y consumidores de mensajes. No queremos que los productores que interfieren entre sí, pero los consumidores deben ser capaces de recuperar los mensajes sin tener que esperar a los productores. Así que sólo creamos un objeto

Object writeLock = new Object();

Y a partir de ahora cada vez de productores quiere añadir un nuevo mensaje que acabamos de bloqueo en él:

synchronized(writeLock){
  // do something
}

Así que los consumidores todavía pueden leer, y los productores serán bloqueados.

método sincronizado

Los métodos sincronizados tienen dos efectos.
En primer lugar, cuando un hilo está ejecutando un método sincronizado para un objeto, todos los otros hilos que invocan métodos para el mismo bloque objeto (suspender la ejecución) hasta que el primer hilo sincronizados se realiza con el objeto.

En segundo lugar, cuando un sincronizados salidas método, se establece automáticamente una sucede-antes relación con cualquier invocación subsiguiente de un método sincronizado para el mismo objeto. Esto garantiza que los cambios en el estado del objeto son visibles para todos los temas.

Tenga en cuenta que los constructores no pueden sincronizarse - usando la palabra clave sincronizada con un constructor es un error de sintaxis. La sincronización de los constructores no tiene sentido, ya que sólo el hilo que crea un objeto debe tener acceso a ella mientras se está construyendo.

Declaración sincronizada

A diferencia de los métodos sincronizados, los estados sincronizados debe especificar el objeto que proporciona el bloqueo intrínseco: Muy a menudo Lo utilizo para sincronizar el acceso a una lista o mapa, pero no quiero bloquear el acceso a todos los métodos del objeto.

Q: intrínsecos Cerraduras y Sincronización La sincronización se construye alrededor de una entidad interna conocida como el bloqueo intrínseco o bloqueo del monitor. (La especificación API menudo se refiere a esta entidad simplemente como un "monitor.") Cerraduras intrínsecas juegan un papel en ambos aspectos de la sincronización: la aplicación de acceso exclusivo al estado de un objeto y el establecimiento sucede-antes relaciones que son esenciales para la visibilidad.

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 bloqueo intrínseca del objeto antes de acceder a ellos, y luego liberar el bloqueo intrínseco cuando se hace con ellos. Un hilo se dice que poseer la cerradura intrínseca entre el tiempo que se ha adquirido el bloqueo y liberada la cerradura. Mientras un hilo posee un bloqueo intrínseco, ningún otro hilo puede adquirir la misma cerradura. El otro hilo bloqueará cuando intenta adquirir el bloqueo.

package test;

public class SynchTest implements Runnable {  
    private int c = 0;

    public static void main(String[] args) {
        new SynchTest().test();
    }

    public void test() {
        // Create the object with the run() method
        Runnable runnable = new SynchTest();
        Runnable runnable2 = new SynchTest();
        // Create the thread supplying it with the runnable object
        Thread thread = new Thread(runnable,"thread-1");
        Thread thread2 = new Thread(runnable,"thread-2");
//      Here the key point is passing same object, if you pass runnable2 for thread2,
//      then its not applicable for synchronization test and that wont give expected
//      output Synchronization method means "it is not possible for two invocations
//      of synchronized methods on the same object to interleave"

        // Start the thread
        thread.start();
        thread2.start();
    }

    public synchronized  void increment() {
        System.out.println("Begin thread " + Thread.currentThread().getName());
        System.out.println(this.hashCode() + "Value of C = " + c);
//      If we uncomment this for synchronized block, then the result would be different
//      synchronized(this) {
            for (int i = 0; i < 9999999; i++) {
                c += i;
            }
//      }
        System.out.println("End thread " + Thread.currentThread().getName());
    }

//    public synchronized void decrement() {
//        System.out.println("Decrement " + Thread.currentThread().getName());
//    }

    public int value() {
        return c;
    }

    @Override
    public void run() {
        this.increment();
    }
}

verificación Cross diferentes salidas con método sincronizado, el bloque y sin sincronización.

Nota:. estática métodos y bloques sincronizados trabajan en la clase de objeto

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}

Cuando el compilador Java convierte el código fuente a código de bytes, que maneja métodos sincronizados y bloques sincronizados de manera muy diferente.

Cuando la JVM realiza un método sincronizado, el hilo de ejecución identifica que la estructura method_info del método tiene el conjunto bandera ACC_SYNCHRONIZED, entonces se adquiere automáticamente bloqueo del objeto, llama al método, y libera el bloqueo. Si se produce una excepción, el hilo libera automáticamente el bloqueo.

Sincronización de un bloque de método, por el contrario, no pasa por la JVM de soporte integrado para la adquisición de bloqueo y el manejo de excepciones de un objeto y requiere que la funcionalidad escribirse explícitamente en el código de bytes. Si se lee el código de bytes de un método con un bloque sincronizado, verá más de una docena de operaciones adicionales para gestionar esta funcionalidad.

Esta muestra las llamadas para generar tanto un método sincronizado y un bloque sincronizado:

public class SynchronizationExample {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

El método synchronizedMethodGet() genera el siguiente código de bytes:

0:  aload_0
1:  getfield
2:  nop
3:  iconst_m1
4:  ireturn

Y aquí está el código de bytes a partir del método synchronizedBlockGet():

0:  aload_0
1:  dup
2:  astore_1
3:  monitorenter
4:  aload_0
5:  getfield
6:  nop
7:  iconst_m1
8:  aload_1
9:  monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow

Una diferencia significativa entre método sincronizado y el bloque es que, bloque sincronizado generalmente a reducir el alcance de cerradura. Como ámbito de bloqueo es inversamente proporcional al rendimiento, siempre es mejor para bloquear única sección crítica de código. Uno de los mejores ejemplo del uso de bloque sincronizado es doble comprobación de bloqueo en el patrón Singleton donde en lugar de bloquear toda método getInstance() sólo cerramos la sección crítica de código que se utiliza para crear la instancia Singleton. Esto mejora el rendimiento drásticamente debido bloqueo sólo se requiere uno o dos veces.

Durante el uso de métodos sincronizados, tendrá que tener un cuidado especial si se mezclan los dos métodos sincronizados estáticos sincronizados y no estáticos.

Lo más a menudo Lo utilizo para sincronizar el acceso a una lista o mapa, pero no quiero bloquear el acceso a todos los métodos del objeto.

En el siguiente código de un hilo modificar la lista no bloqueará la espera de un hilo que se está modificando el mapa. Si los métodos se sincronizaron en el objeto a continuación, cada método tendría que esperar a pesar de las modificaciones que están haciendo ¿no conflicto.

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}

Con los bloques sincronizados, puede tener varios sincronizadores, de modo que múltiples simultáneas, pero no conflictivos cosas pueden ir al mismo tiempo.

Los métodos sincronizados pueden comprobarse utilizando la API de reflexión. Esto puede ser útil para probar algunos contratos, como todos los métodos en el modelo están sincronizados .

Los siguientes impresiones fragmento de todos los métodos sincronizados de Hashtable:

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}

Nota importante sobre el uso del bloque sincronizado: cuidado con lo que el uso de objetos como bloqueo

El fragmento de código de user2277816 anterior ilustra este punto en el que una referencia a una cadena literal se utiliza como bloqueo de objetos. Darse cuenta de que la cadena literales están internados de forma automática en Java y debería empezar a ver el problema: cada pieza de código que se sincroniza en el "bloqueo" literal, comparte la misma cerradura! Esto puede conducir fácilmente a los puntos muertos con piezas que no tienen relación de código.

No son sólo los objetos String que debe tener cuidado con. primitivas en caja son también un peligro, ya que autoboxing y los métodos valueOf pueden reutilizar los mismos objetos, dependiendo del valor.

Para más información ver: https: / /www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused

A menudo, el uso de un bloqueo en un nivel de método es demasiado grosero. ¿Por qué encerrar a un trozo de código que no accederán a los recursos compartidos por encerrar a un método completo. Puesto que cada objeto tiene un bloqueo, se pueden crear objetos ficticios para implementar bloque de sincronización de nivel. El nivel de bloque es más eficiente, ya que no se bloquea todo el método.

A continuación, algunos ejemplos

Método Nivel

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

Bloquear nivel

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[Editar]

Para Collection como Vector y Hashtable que se sincronizan cuando ArrayList o HashMap no lo son y que necesitan establecer palabra clave sincronizada o invocan Colecciones método sincronizado:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list

La única diferencia: bloques sincronizados permite el bloqueo granular a diferencia de método sincronizado

bloque o métodos Básicamente synchronized se han utilizado para escribir código seguro de rosca, evitando errores de incoherencia de memoria.

Esta pregunta es muy antiguo y muchas cosas han cambiado durante los últimos 7 años. Nuevas construcciones de programación se han introducido para la seguridad de los subprocesos.

Se puede lograr la seguridad hilo mediante el uso de la API de concurrencia avanzada en lugar de bloques synchronied. Esta documentación página ofrece una buena programación construye para lograr la seguridad hilo.

Bloqueo de objetos apoyo modismos que simplifican muchas aplicaciones simultáneas de bloqueo.

Executors definir una API de alto nivel para el lanzamiento y gestión de hilos. implementaciones ejecutor proporcionadas por java.util.concurrent proporcionan gestión de grupo de subprocesos adecuado para aplicaciones a gran escala.

Colecciones Concurrentes hacer que sea más fácil de manejar grandes colecciones de datos, y puede reducir en gran medida la necesidad de sincronización.

Las variables atómicas tener características que minimizan la sincronización y ayudar a evitar errores de coherencia de memoria.

ThreadLocalRandom (en JDK 7) proporciona la generación eficiente de números pseudoaleatorios desde varios subprocesos.

Una mejor reemplazo para sincronizada es ReentrantLock, que utiliza API Lock

  

A reentrante Lock exclusión mutua con el mismo comportamiento básico y semántica que el bloqueo del monitor implícita acceder usando métodos y declaraciones sincronizados, pero con capacidades extendidas.

Ejemplo con cerraduras:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

Consulte java.util .concurrent y paquetes java.util.concurrent.atomic también para otras construcciones de programación.

Consulte esta pregunta relacionada también:

sincronización vs Bloqueo

método sincronizado se utiliza para el bloqueo de todos los objetos bloque sincronizado se utiliza para bloquear objeto específico

En general, estos son en su mayoría de la misma, aparte de ser explícita sobre el monitor del objeto que está siendo utilizado contra la implícita este objeto. Una desventaja de los métodos sincronizados que creo que a veces se pasa por alto es que en el uso del "este" de referencia para sincronizar el que se deja abierta la posibilidad de que los objetos externos de bloqueo sobre el mismo objeto. Eso puede ser un error muy sutil si llegas a ella. Sincronización en un objeto explícito interna u otro campo existente puede evitar este problema, que encapsula completamente la sincronización.

Como ya se ha dicho bloque aquí sincronizado puede utilizar variable definida por el usuario como objeto de bloqueo, cuando la función sincronizada utiliza sólo "este". Y, por supuesto, se puede manipular con las áreas de su función que deben estar sincronizados. Pero todo el mundo dice que no hay diferencia entre la función sincronizada y el bloque que cubre toda la función utilizando "este" objeto como bloqueo. Eso no es cierto, diferencia está en el código de bytes que se generará en ambas situaciones. En caso de uso bloque sincronizado deben ser asignados variable local que mantiene la referencia a "este". Y como resultado tendremos un poco más de gran tamaño para la función (no es relevante si sólo tiene unos pocos número de funciones).

explicación más detallada de la diferencia que puede encontrar aquí: http://www.artima.com/insidejvm/ed2/threadsynchP.html

En el caso de métodos sincronizados, bloqueo se adquirieron en un objeto. Pero si vas con bloque sincronizado usted tiene una opción para especificar un objeto sobre el que se adquirió la cerradura.

Ejemplo:

    Class Example {
    String test = "abc";
    // lock will be acquired on String  test object.
    synchronized (test) {
        // do something
    }

   lock will be acquired on Example Object
   public synchronized void testMethod() {
     // do some thing
   } 

   }

Sé que esta es una vieja pregunta, pero con mi rápida lectura de las respuestas aquí, realmente no vi a nadie mencionar eso a veces synchronized El método puede ser el equivocado cerrar con llave.
De Concurrencia de Java en la práctica (pág.72):

public class ListHelper<E> {
  public List<E> list = Collections.syncrhonizedList(new ArrayList<>());
...

public syncrhonized boolean putIfAbsent(E x) {
 boolean absent = !list.contains(x);
if(absent) {
 list.add(x);
}
return absent;
}

El código anterior tiene el apariencia de ser seguro para subprocesos.Sin embargo, en realidad no lo es.En este caso el bloqueo se obtiene en la instancia de la clase.Sin embargo, es posible que el lista para ser modificado por otro hilo que no utilice ese método.El enfoque correcto sería utilizar

public boolean putIfAbsent(E x) {
 synchronized(list) {
  boolean absent = !list.contains(x);
  if(absent) {
    list.add(x);
  }
  return absent;
}
}

El código anterior bloquearía todos los temas tratando de modificar lista desde que se modifica la lista hasta que se completa el bloque sincronizado.

Como cuestión práctica, la ventaja de los métodos sincronizado a través de bloques sincronizados es que son más idiota resistente; porque no se puede elegir un objeto arbitrario para bloquear en, no se puede abusar de la sintaxis del método sincronizado para hacer cosas estúpidas como bloqueo en una cadena literal o de bloqueo en el contenido de un campo mutable que se cambia de debajo de las roscas.

Por otro lado, con métodos sincronizados no se puede proteger el bloqueo de conseguir adquirida por cualquier tema que se puede obtener una referencia al objeto.

Así que usando sincronizada como un modificador de métodos es mejor en la protección de sus vaca-os trabajadores se haga daño a sí mismos, mientras que el uso de bloques sincronizados junto con objetos de bloqueo final privado es mejor en la protección de su propio código de la vaca-os trabajadores.

A partir de un resumen especificación de Java: http://www.cs.cornell.edu/andru/javaspec/17 .doc.html

  

La declaración sincronizado (§14.17) calcula una referencia a un objeto;   a continuación, intenta realizar una acción de bloqueo en ese objeto y no lo hace   seguir adelante hasta que la acción de bloqueo ha completado con éxito. ...

     

Un método sincronizado (§8.4.3.5) realiza automáticamente una acción de bloqueo   cuando se invoca; su cuerpo no se ejecuta hasta que la acción de bloqueo tiene   completado con éxito. Si el método es un método de instancia , se   bloquea la cerradura asociada con la instancia para la que fue invocado   (Es decir, el objeto que será conocido como este durante la ejecución de   el cuerpo del método). Si el método es estático , se bloquea el   cerradura asociado con el objeto de clase que representa la clase en   que está definido el método. ...

Sobre la base de estas descripciones, diría respuestas anteriores son correctas, y un método sincronizado podría ser especialmente útil para los métodos estáticos, en las que de otra manera tendrían que encontrar la manera de conseguir el "objeto de clase que representa la clase en la cual se definió el método ".

Edit: Al principio pensé que se trataba de las cotizaciones de la especificación Java real. Aclaró que esta página es sólo un resumen / explicación de la especificación

TLDR; Ni utilizar el modificador synchronized ni la expresión synchronized(this){...} pero synchronized(myLock){...} donde myLock es un campo última instancia que sostiene un objeto privado

.

La diferencia entre usar el modificador synchronized en la declaración del método y la expresión synchronized(..){ } en el cuerpo del método son esto:

  • El modificador synchronized especificado en la firma del método
    1. es visible en el JavaDoc generado,
    2. es determinable por software a través de reflexión al probar modificador de un método para Modifier.SYNCHRONIZED ,
    3. requiere menos escribir y sangría en comparación con synchronized(this) { .... }, y
    4. (dependiendo de su IDE) es visible en el esquema de la clase y el código de finalización,
    5. utiliza el objeto this como bloqueo cuando se declaran en el método no estático o la clase envolvente cuando declaró en un método estático.
  • La expresión synchronized(...){...} que permite
    1. sólo a sincronizar la ejecución de partes del cuerpo de un método,
    2. para ser utilizado dentro de un constructor o un ( estática ) bloque de inicialización,
    3. para elegir el objeto de bloqueo que controla el acceso sincronizado.

Sin embargo, utilizando el modificador synchronized o synchronized(...) {...} con this como el objeto de bloqueo (como en synchronized(this) {...}), tienen la misma desventaja. Tanto el uso de su propia instancia que el objeto de bloqueo para sincronizar sucesivamente. Esto es peligroso porque no sólo el objeto en sí pero cualquier otro objeto externo / código que contiene una referencia a ese objeto también se puede utilizar como un bloqueo de sincronización con efectos secundarios potencialmente graves (degradación del rendimiento y interbloqueos ).

Por lo tanto mejor práctica es ni utilizar el modificador synchronized ni la expresión synchronized(...) en conjunción con this como objeto de bloqueo, sino un objeto de bloqueo privado a este objeto. Por ejemplo:

public class MyService {
    private final lock = new Object();

    public void doThis() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }

    public void doThat() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }
}

También puede utilizar varios objetos de bloqueo, pero cuidado especial debe tenerse para asegurar que esto no da lugar a callejones sin salida cuando se usa anidado.

public class MyService {
    private final lock1 = new Object();
    private final lock2 = new Object();

    public void doThis() {
       synchronized(lock1) {
          synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThat() and doMore().
          }
    }

    public void doThat() {
       synchronized(lock1) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doMore() may execute concurrently
        }
    }

    public void doMore() {
       synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doThat() may execute concurrently
        }
    }
}

supongo que esta pregunta se refiere a la diferencia entre Hilo Singleton seguridad y inicialización perezosa con cheque doble bloqueo . Siempre consulte este artículo cuando necesito para implementar algunas Singleton específica.

Bueno, esto es un hilo de seguridad Singleton

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 
  

Pros:

     
      
  1. inicialización Lazy es posible.

  2.   
  3. Es seguro para subprocesos.

  4.   
     

Contras:

     
      
  1. getInstance () método se sincroniza por lo que produce un rendimiento lento como varios subprocesos no puede acceder a él de forma simultánea.
  2.   

Este es un inicialización perezosa con cheque doble bloqueo

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 
  

Pros:

     
      
  1. inicialización Lazy es posible.

  2.   
  3. También se hilo de seguridad.

  4.   
  5. Rendimiento reducida a causa de la palabra clave sincronizada se supera.

  6.   
     

Contras:

     
      
  1. La primera vez, puede afectar al rendimiento.

  2.   
  3. Como contras. de método de doble comprobación de bloqueo es soportable por lo que puede ser   utilizado para el alto rendimiento aplicaciones de subprocesos múltiples.

  4.   

Por favor, consulte este artículo para más detalles:

https://www.geeksforgeeks.org/java- singleton-design-patrón-prácticas-ejemplos /

Sincronización con hilos. 1) NUNCA use sincronizado (este) en un hilo no funciona. Sincronización con (esto) usa el subproceso actual como el objeto rosca de bloqueo. Puesto que cada hilo es independiente de otros hilos, no hay coordinación de la sincronización. 2) Las pruebas de código muestran que en Java 1.6 en un Mac la sincronización método no funciona. 3) sincronizado (lockObj) donde lockObj es un objeto compartido común de todas las discusiones Sincronización en la que va a trabajar. 4) ReenterantLock.lock () y .unlock trabajo (). Ver tutoriales de Java para esto.

El código siguiente muestra estos puntos. También contiene el vector thread-safe que sería sustituido por el ArrayList, para mostrar que la adición de muchos hilos a un vector no pierden ninguna información, mientras que la misma con un ArrayList puede perder información. 0) Código actual muestra la pérdida de información debido a las condiciones de carrera A) Comentario la corriente marcada una línea, y elimine la línea A por encima de ella, a continuación, ejecutar, el método pierde datos, pero que no debería. B) paso Reverse A, B uncomment y // bloque end}. A continuación, ejecute a ver resultados sin pérdida de datos C) Comente B, elimine C. Ejecutar, consulte Sincronización en la (este) pierde los datos, como se esperaba. ¿No tiene tiempo para completar todas las variaciones, espero que esto ayude. Si la sincronización en (este), o las obras de sincronización método, indique qué versión de Java y sistema operativo que la prueba. Gracias.

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top