java multithreading static synchronization static-initializer

¿Son seguros los inicializadores estáticos de Java?



multithreading static (6)

Así que, básicamente, dado que desea una instancia de singleton, debe hacerlo más o menos a la antigua usanza y asegúrese de que su objeto singleton se inicialice una vez y solo una vez.

Estoy usando un bloque de código estático para inicializar algunos controladores en un registro que tengo. Mi pregunta es, por lo tanto, ¿puedo garantizar que este bloque de código estático solo se llame una vez cuando se cargue la clase por primera vez? Entiendo que no puedo garantizar cuándo se llamará este bloque de código, supongo que es cuando el cargador de clases lo carga por primera vez. Me doy cuenta de que podría sincronizar en la clase en el bloque de código estático, pero mi suposición es ¿esto es realmente lo que sucede de todos modos?

Ejemplo de código simple sería;

class FooRegistry { static { //this code must only ever be called once addController(new FooControllerImpl()); } private static void addController(IFooController controller) { // ... } }

o debería hacer esto;

class FooRegistry { static { synchronized(FooRegistry.class) { addController(new FooControllerImpl()); } } private static void addController(IFooController controller) { // ... } }


En circunstancias normales, todo en el inicializador estático ocurre, antes que todo lo que usa esa clase, por lo que la sincronización no suele ser necesaria. Sin embargo, la clase es accesible para cualquier cosa que invoque el intiailizador estático (lo que incluye provocar la invocación de otros inicializadores estáticos).

Una clase puede ser cargada por una clase cargada pero no necesariamente inicializada de inmediato. Por supuesto, una clase puede ser cargada por múltiples instancias de cargadores de clases y por lo tanto convertirse en múltiples clases con el mismo nombre.


Este es un truco que puedes usar para la inicialización perezosa

enum Singleton { INSTANCE; }

o para pre Java 5.0

class Singleton { static class SingletonHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton instance() { return SingletonHolder.INSTANCE; } }

Como el bloque estático en SingletonHolder se ejecutará una vez de manera segura, no necesita ningún otro bloqueo. La clase SingletonHolder solo se cargará cuando llame a instance ()


Sí, los inicializadores estáticos de Java son seguros para subprocesos (use su primera opción).

Sin embargo, si desea asegurarse de que el código se ejecuta exactamente una vez, debe asegurarse de que la clase solo se carga con un único cargador de clases. La inicialización estática se realiza una vez por cargador de clases.



Sí, tipo de

Un inicializador static solo se llama una vez, por lo que según esa definición es seguro para subprocesos: necesitaría dos o más invocaciones del inicializador static para obtener incluso la contención de subprocesos.

Dicho esto, static inicializadores static son confusos de muchas otras maneras. Realmente no hay un orden específico en el que se llaman. Esto se vuelve realmente confuso si tiene dos clases cuyos inicializadores static dependen el uno del otro. Y si usa una clase pero no usa lo que configurará el inicializador static , no se garantiza que el cargador de clases invoque el inicializador estático.

Finalmente, tenga en cuenta los objetos en los que se está sincronizando. Me doy cuenta de que esto no es realmente lo que estás preguntando, pero asegúrate de que tu pregunta realmente no pregunte si necesitas hacer que addController() seguro para la ejecución de subprocesos.