Pregunta

En Java, la asignación es atómico si el tamaño de la variable es menor o igual a 32 bits pero no se si más de 32 bits.

Lo que (volátil/sincronizada) sería más eficiente para su uso en caso de doble o asignación?

Como,

  volatile double x = y;

sincronizado no es aplicable con un primitivo argumento.¿Cómo puedo usar sincronizado en este caso?Por supuesto no quiero bloquear mi clase, por lo que this no debe ser utilizado.

¿Fue útil?

Solución

Si usted encuentra de bloqueo en el objeto en sí demasiado pesado, entonces sincronizada es el camino a seguir. Antes de Java 1.5 volátil puede haber sido una buena elección, pero ahora volátil puede tener un impacto muy grande, obligando pedido instrucciones sobre el método donde sucede la asignación. Crear un objeto independiente (private final Object X_LOCK = new Object();) y de sincronización en él al establecer u obtener el valor de esa doble. Esto le dará un nivel fino de control sobre el bloqueo, que parece que necesita.

En el nuevo paquete de concurrencia hay más opciones, como AtomicReference que pueden ser un sustituto para la buena volátil si realmente necesita para la sincronización de evitar.

Otros consejos

¿Qué estás tratando de hacer?El synchronized y volatile las palabras clave son mecanismos en Java que puede ser usado para asegurar que los valores coherentes son observados por los diferentes hilos de la lectura de los mismos datos.En particular, permiten a la razón sobre ocurre antes de las relaciones en sus programas.

Usted simplemente no puede evitar el uso de uno de volatile o synchronized con el fin de poder acceder a la no-final campos en un multi-threaded programa.Dicho esto, la principal razón por la que son propensos a requerir synchronized más volatile es el requisito para el uso de atomic comparar y establecer operaciones (es decir, no va a ser el rendimiento de cualquier consideración).Por ejemplo, en un multi-threaded programa:

volatile int i = 0;

public void foo() { 
    if (i == 0) i = i + 1;
}

El código anterior es inherentemente inseguro, incluso a pesar de la declaración de la variable como volátil significa que las lecturas y escrituras se vacían a la memoria principal - la única aplicación de este método sería algo como:

int i = 0;

public synchronized void foo() {
    if (i == 0) i = i + 1;
}

Así que si usted prefiere?Bueno, si usted tiene múltiples hilos de la modificación de un campo depende de que el valor del campo (es decir,comparar y set), entonces synchronized es la única solución segura.

También vale la pena decir: la sobrecarga de rendimiento de synchronized no es un problema (en la inmensa mayoría de los casos).La sincronización de los problemas de rendimiento son generalmente debido a la innecesaria de código de cuellos de botella, interbloqueos o livelocks y puede ser mitigado si es necesario.Cualquier puro reloj de los ciclos generales será eclipsada por otras cosas que aplicación:e / s de archivos, consultas de base de datos, remoting, etc.

volátil es sin duda el camino a seguir si sólo se está haciendo una asignación. Estoy seguro de que sabes, pero ya que se crió: si le gustaría hacer operaciones más complejas (incrementar el valor, por ejemplo) que se necesita para syncrhonize. i ++ no es nunca hilo de seguridad para cualquier tipo de variable. Usted necesita sincronía. i ++ y similares, ya que en realidad es más de 1 operación.

No: Se expresó que se podría utilizar AtomicDouble pero actualmente no hay AtomicDouble en java.util.concurrent.atomic

Si usted está haciendo un múltiples operaciones en X, que requiere ajuste a un nuevo valor al final, es posible hacer esto de una manera segura hilo sin bloqueo lo que nunca, y tiene que ser seguro para hilos, utilizando comparar y ajustar. Ejemplo:

AtomicLong x = new AtomicLong(SomeValue);
public void doStuff() {
  double oldX;
  double newX;
  do {
    oldX = x.get();
    newX = calculateNewX(oldX);
  } while (!x.compareAndSet
      (Double.doubleToLongBits(oldX), Double.doubleToLongBits(newX)));

Esto funciona porque compareAndSet verá si el valor de x ha cambiado desde la última vez que lo lea. Si x ha cambiado entonces se ven obligados a hacer el cálculo de nuevo y volver a intentar el establecimiento de la misma.

Se puede aplicar, por supuesto, su propio AtomicDouble en vez de hacer estas conversiones doubleToLongBits. Echar un vistazo a AtomicFieldUpdater.

KDSRathore, puede utilizar algunos bloqueos explícitos, o hacer algún objeto ficticio Object = new Object (), en la que se sincroniza en setter / getter de ese doble

De acuerdo con la documentación de Oracle , puede utilizar volátil para referirse al objeto doble:

volatile Double x = y;

"escribe y lee las referencias son siempre atómica, independientemente de si se implementan como valores de 32 bits o 64 bits."

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top