Pregunta

Considere francotirador código de abajo:

package sync;

public class LockQuestion {
    private String mutable;

    public synchronized void setMutable(String mutable) {
        this.mutable = mutable;
    }

    public String getMutable() {
        return mutable;
    }   
}

A la hora Time1 hilo Thread1 actualizará la variable ‘mutable’. La sincronización se necesita en la moda con el fin de la memoria caché local al ras de la memoria principal. A la hora Time2 (Time2> Time1, sin contención de rosca) Rosca Thread2 leerá valor de mutable.

La pregunta es - qué necesito para poner sincronizado antes captador? Parece que este no causa ningún problema -. De memoria deben estar al día y la memoria caché local de Thread2 deben ser invalidado y actualizada por Thread1, pero no estoy seguro

¿Fue útil?

Solución

En lugar de maravilla, ¿por qué no usar las referencias atómicas en java.util.concurrent ?

(y por lo que vale la pena, mi lectura de sucede antes no garantiza que Thread2 verá cambios en mutable a menos que también utiliza sincronizada ... pero siempre me da un dolor de cabeza que parte de los JLS, a fin de utilizar las referencias atómicas)

Otros consejos

Se va a estar bien si haces detalles mutables volátil, en la " cerradura barato de lectura-escritura "

¿Estás absolutamente seguro de que el comprador se llamará sólo después de la incubadora se llama? Si es así, no es necesario que el getter que sincronizarse, ya lecturas simultáneas no necesitan sincronizarse.

Si hay una posibilidad de que obtener y establecer al mismo tiempo que se puede llamar entonces definitivamente necesidad de sincronizar los dos.

Si usted se preocupa tanto por el rendimiento en el hilo de la lectura, entonces lo que hace es leer el valor de una vez usando una correcta sincronización o referencias volátiles o atómicas. A continuación, se asigna el valor a una variable simple y llano.

La asignar a la variable normal se garantiza que pasará después de la lectura atómica (porque qué otra manera podría obtener el valor?) Y si el valor nunca se escribirá por otro subproceso nuevo que está todo listo.

creo que debería empezar con algo que es correcto y optimizar más tarde, cuando usted sabe que tiene un problema. Yo sólo uso AtomicReference menos unos pocos nano-segundos es demasiado largo. ;)

public static void main(String... args) {
    AtomicReference<String> ars = new AtomicReference<String>();
    ars.set("hello");
    long start = System.nanoTime();
    int runs = 1000* 1000 * 1000;
    int length = test(ars, runs);
    long time = System.nanoTime() - start;
    System.out.printf("get() costs " + 1000*time / runs + " ps.");
}

private static int test(AtomicReference<String> ars, int runs) {
    int len = 0;
    for (int i = 0; i < runs; i++)
        len = ars.get().length();
    return len;
}

Prints

get() costs 1219 ps.

ps es un pico-segundos, con es 1 millonésima parte de un micro-segundo.

Esto probablemente no dar lugar a un comportamiento incorrecto, pero a menos que también se garantiza el orden en que los hilos de inicio en, no se puede necesariamente garantía de que el compilador no lo hizo cambiar el orden de lectura en Thread2 antes de la escritura en Thread1. Más específicamente, todo el tiempo de ejecución de Java sólo se tiene que garantía de que los hilos se ejecutan como si se llevaron a cabo en serie. Por lo tanto, siempre que el hilo tiene la misma salida se ejecuta en serie bajo optimizaciones, toda la pila de idioma (compilador, hardware, Language Runtime) puede hacer prácticamente todo lo que quiere. Incluyendo permitir Thread2 para almacenar en caché el resultado de LockQuestion.getMutable().

En la práctica, yo estaría muy sorprendido si le ha pasado. Si quiere garantía de que esto no suceda, tienen LockQuestion.mutable ser declarado como final y que éste se inicia en el constructor. O utilizar el siguiente idioma :

private static class LazySomethingHolder {
  public static Something something = new Something();
}

public static Something getInstance() {
  return LazySomethingHolder.something;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top