c# - usar - variable static java




¿Es seguro el subproceso estático de C#? (7)

En otras palabras, es seguro este hilo de implementación de Singleton:

public class Singleton
{
    private static Singleton instance;

    private Singleton() { }

    static Singleton()
    {
        instance = new Singleton();
    }

    public static Singleton Instance
    {
        get { return instance; }
    }
}

Aquí está la versión de Cliffnotes de la página de MSDN anterior en c # singleton:

Usa el siguiente patrón, siempre, no te puedes equivocar:

public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();

   private Singleton(){}

   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}

Más allá de las características obvias de singleton, te ofrece estas dos cosas de forma gratuita (con respecto a singleton en c ++):

  1. construcción perezosa (o ninguna construcción si nunca fue llamada)
  2. sincronización

Aunque otras respuestas son en su mayoría correctas, hay otra advertencia con los constructores estáticos.

Según la sección II.10.5.3.3 Razas y puntos muertos de la infraestructura de lenguaje común ECMA-335

La inicialización de tipo por sí sola no creará un interbloqueo a menos que algún código llamado desde un inicializador de tipo (directa o indirectamente) invoque explícitamente las operaciones de bloqueo.

El siguiente código da como resultado un punto muerto

using System.Threading;
class MyClass
{
    static void Main() { /* Won’t run... the static constructor deadlocks */  }

    static MyClass()
    {
        Thread thread = new Thread(arg => { });
        thread.Start();
        thread.Join();
    }
}

El autor original es Igor Ostrovsky, vea su post here .


La especificación de Common Language Infrastructure garantiza que "un inicializador de tipo se ejecutará exactamente una vez para cualquier tipo dado, a menos que el código de usuario lo llame explícitamente". (Sección 9.5.3.1.) Por lo tanto, a menos que tenga alguna IL extraña perdida llamando a Singleton :: .cctor directamente (improbable) su constructor estático se ejecutará exactamente una vez antes de que se use el tipo Singleton, solo se creará una instancia de Singleton, y su propiedad Instancia es segura para subprocesos.

Tenga en cuenta que si el constructor de Singleton accede a la propiedad Instancia (incluso de manera indirecta), la propiedad Instancia será nula. Lo mejor que puede hacer es detectar cuándo sucede esto y lanzar una excepción, al verificar que la instancia no sea nula en el acceso a la propiedad. Después de que su constructor estático complete, la propiedad Instancia no será nula.

Como la respuesta de Zoomba señala, deberá hacer que Singleton sea seguro para acceder desde múltiples hilos, o implementar un mecanismo de bloqueo utilizando la instancia de Singleton.



Se garantiza que los constructores estáticos se ejecutarán solo una vez por dominio de aplicación, antes de que se creen las instancias de una clase o se acceda a los miembros estáticos. http://msdn.microsoft.com/en-us/library/aa645612.aspx

La implementación que se muestra es segura para subprocesos para la construcción inicial, es decir, no se requiere bloqueo o prueba nula para construir el objeto Singleton. Sin embargo, esto no significa que cualquier uso de la instancia se sincronizará. Hay una variedad de formas en que esto se puede hacer; He mostrado uno abajo.

public class Singleton
{
    private static Singleton instance;
    // Added a static mutex for synchronising use of instance.
    private static System.Threading.Mutex mutex;
    private Singleton() { }
    static Singleton()
    {
        instance = new Singleton();
        mutex = new System.Threading.Mutex();
    }

    public static Singleton Acquire()
    {
        mutex.WaitOne();
        return instance;
    }

    // Each call to Acquire() requires a call to Release()
    public static void Release()
    {
        mutex.ReleaseMutex();
    }
}

Si bien todas estas respuestas dan la misma respuesta general, hay una advertencia.

Recuerde que todas las derivaciones potenciales de una clase genérica se compilan como tipos individuales. Por lo tanto, tenga cuidado al implementar constructores estáticos para tipos genéricos.

class MyObject<T>
{
    static MyObject() 
    {
       //this code will get executed for each T.
    }
}

EDITAR:

Aquí está la demostración:

static void Main(string[] args)
{
    var obj = new Foo<object>();
    var obj2 = new Foo<string>();
}

public class Foo<T>
{
    static Foo()
    {
         System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));        
    }
}

En la consola:

Hit System.Object
Hit System.String

Usar un constructor estático en realidad es seguro para hilos. El constructor estático está garantizado para ejecutarse solo una vez.

De la especificación de lenguaje C # http://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx :

El constructor estático para una clase se ejecuta como máximo una vez en un dominio de aplicación dado. La ejecución de un constructor estático es activada por el primero de los siguientes eventos que ocurren dentro de un dominio de aplicación:

  • Se crea una instancia de la clase.
  • Se hace referencia a cualquiera de los miembros estáticos de la clase.

Así que sí, puedes confiar en que tu singleton será correctamente instanciado.

Zooba hizo un punto excelente (¡y 15 segundos antes que yo, también!) De que el constructor estático no garantizará un acceso compartido seguro al subproceso. Eso tendrá que ser manejado de otra manera.





singleton