Pregunta

private static Callback callback;

public Foo()
{
    super(getCallback());
}

private static Callback getCallback()
{
    callback = new Callback();
    return callback;
}

Foo Constructor () potencialmente puede ser llamado desde varios subprocesos. Mi preocupación es con el ámbito privado 'callback' estático y el método estático 'getCallback ()'.

Como se puede ver, cada vez que 'getCallback ()' se llama, se le asigna un nuevo valor a 'callback' estática campo.

Mi conjetura es que no es hilo de seguridad por la palabra clave estática está siempre unida a la clase no la instancia, por lo que significa, el campo estático 'callback' de un Foo potencialmente pueden ser sobrescritos por otro hilo que está construyendo otro Foo (). ¿Es esto correcto?

Por favor, corríjanme si estoy equivocado. Gracias!

EDIT: Mi intención es mantener 'devolución de llamada' en algún lugar de la clase, por lo que puede volver a utilizarlo más adelante. Pero esto no es fácil porque Foo se extiende desde una clase que tiene constructor obligatoriedad 'callback' que se transmite.

¿Fue útil?

Solución

Sí, estás en lo correcto. Es posible que dos instancias de Foo a terminan con la misma instancia CallBack cuando dos hilos entran en el método getCallback() simultáneamente y uno asigna un nuevo CallBack al campo estático mientras que el otro ya ha hecho esto, pero aún no devuelto. En este caso, la mejor solución es no tener el campo estático, ya que no sirve para nada. Alternativamente, hacer getCallback() sincronizado.

Pero tenga en cuenta que se trata de no cierto que sólo las palabras clave static resultados en código que no se threadsafe.

Otros consejos

No es seguro para subprocesos. Prueba estas opciones:

Opción 1: aquí todas las instancias comparten el mismo devolución de llamada

private static final Callback callback = new Callback();

public Foo() {
    super(callback);
}

Opción 2: aquí cada instancia tiene su propia devolución de llamada

public Foo() {
    super(new Callback());
}

Tenga en cuenta que en ambos casos, aunque el constructor es seguro para subprocesos, el hilo de la seguridad de toda la clase depende de la implementación de devolución de llamada. Si tiene estado mutable, entonces usted tendrá problemas potenciales. Si devolución de llamada es inmutable, entonces usted tiene hilos de seguridad.

Devolución de llamada tendrá un nuevo valor cada vez Foo () se llama (incluso desde el mismo hilo). No estoy muy seguro de lo que el código debe estar haciendo (si desea inicializar la variable estática sólo una vez (Singleton), usted debe comprobar si sigue siendo nulo en getCallback () - y lo que es actionCallback?). Por lo que es seguro para subprocesos, utilice sincronizada.

Creo que lo resumió perfectamente a sí mismo, pero sin más detalles acerca de lo que está tratando de lograr que será difícil de hacer sugerencias para arreglar el problema.

Una pregunta obvia es, ¿callback tiene por qué ser estática? O podría hacerlo de manera segura un campo de instancia sin romper la funcionalidad de su clase?

Sé que ha sido contestada pero el por qué en realidad no se ha detallado.

dos hilos están llamando el método getCallback (), podrían ejecutar las líneas como sigue:

  1. Thread 1 - devolución de llamada = new devolución de llamada ();
  2. Thread 2 - devolución de llamada = new devolución de llamada ();
  3. Tema 1 - return actionCallback;
  4. Tema 2 - volver actionCallback;

En este caso, la devolución de llamada generado en (2.) serían devueltos en ambos (3.) y (4).

La solución parece ser que preguntar por qué de devolución de llamada definido estáticamente si es específico de la instancia no clase.

Espero que ayude.

Lo que estamos tratando de hacer que se llama un patrón Singleton, si usted hace una búsqueda se puede averiguar por qué su generalmente una buena idea para evitar este patrón si se puede, sin embargo, si lo necesita, puede hacer lo siguiente.

private static final Callback CALLBACK= new Callback();

O si usted necesita un Singleton vago que puede hacer

public class Foo {
   class CallbackHolder {
       static final Callback CALLBACK= new Callback();
   }

   public static Callback getCallback() {
      return CallbackHolder.CALLBACK;
   }

public Foo() {
    super(getCallback());
}

Ambas implementaciones son seguros para subprocesos.

¿Quieres una devolución de llamada por hilo, uno por cada objeto, o una verdadera Singleton?

Algunos bocetos de cómo hacer las diferentes variantes - sólo desde la parte superior de mi cabeza, no toman estos demasiado literalmente:)

Tenga en cuenta que he asumido que la devolución de llamada tiene un constructor no trivial que pudiera lanzar una excepción que debe ser manejado, si se trata de un constructor trivial puede simplificar todo esto mucho.

Uno por hilo:

  private static ThreadLocal<Callback> callback;

  public Foo()
  {
      super(getCallback());
  }

  private static Callback getCallback()
  {
      if ( callback.get() == null ) 
          callback.set(new Callback());
      return callback.get();
  }

devolución de llamada único para todas las discusiones:

  private final static Callback callback;

  static {
      callback = new Callback(); 
  }

  public Foo()
  {
      super(getCallback());
  }

  private static Callback getCallback()
  {
      return callback;
  }

Y, por completitud, una devolución de llamada por objeto:

  private Callback callback;

  public Foo()
  {
      super(getCallback());
  }

  private Callback getCallback()
  {
      callback = new Callback();
      return callback;
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top