Cómo actualizar el caché desde múltiples hilos

Tengo un Runnable que tiene un caché (de tipo Cache ) y suponemos que ofrece operaciones seguras para subprocesos. Este objeto Runnable es utilizado por múltiples hilos.

Nuestros hilos obtienen objetos de fuentes externas y luego

  1. verificar si la clave del objeto existe en el caché
  2. Si no, entonces pon
  3. Si ya está en el caché, actualice

Estoy buscando el esquema correcto (es decir, synchronizedcódigo mínimo ) para trabajar con el caché, de manera confiable.

Se me ocurrió el siguiente esquema:

    MyObject current = cache.getIfPresent(givenKey);
    if (current == null) {
        MyObject prev = cache.asMap().putIfAbsent(givenKey, givenObj);
        if (prev == null) {
            // successful put in cache
            return givenObj;
        }
    }

    // current != null or another thread update
    synchronized (current) {
        return update(current, givenObj); // in place change of current
    }

Las ideas clave detrás de mi esquema + "prueba" de fiabilidad:

  1. Si los hilos funcionan en claves diferentes, entonces no es necesario bloquear
  2. Si currentes así null, dado que el caché es seguro para subprocesos, exactamente un subproceso podrá colocar el objeto en el caché mientras que los demás veránprev != null
  3. Los otros hilos deben actualizarse en serie. Observe que estoy sincronizando current, el objeto que se actualizará.

Preguntas

  1. ¿Es confiable mi esquema?
  2. Puede ser optimizado?
  3. En algunos casos, volatiledebe usarse para hacer que la sincronización de memoria sea confiable. ¿Lo necesito aquí?

¡Gracias!

Respuesta 1

1) no, su esquema no es confiable No debe llamar

cache.asMap().putIfAbsent(givenKey, givenObj);

por el método de documentación guava cache.get (clave K, cargador invocable) es preferible que usar métodos asMap.

2) sí, se puede optimizar Debe llamar a este método:

cache.get(K key, Callable<? extends V> loader)

Este método devolverá el valor si ya está en la memoria caché, o agregará el valor del cargador a la memoria caché si el valor no está en la memoria caché y lo devuelve.

así por ejemplo:

 MyObject objInCache =  cache.get(givenKey, ()->givenObj)

if(!objInCache.equals(givenobj)){
 //obje was in the cache,
//update object
}

3) no necesita volátil si el caché es seguro para subprocesos

Respuesta: 2

import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Scanner; copia de seguridad de clase pública {...

Necesito agregar una imagen CMYK (java.awt.BufferedImage) a un documento PDF con iText. Estoy tratando de hacerlo con: com.lowagie.text.Image img = Image.getInstance (BufferedImage, bgColor); Esto produce un ...

Cómo puedo almacenar la consola de salida del servidor en server.log, al igual que la salida de netbeans apache output console server.log para rastrear errores de sql y mostrar system.out.println que he intentado configurar ...

Clase base animal clase pública Animal {cerdo de cordel protegido; perro de cuerda protegido; gato de cuerda protegido; public void setPig (String pig_) {pig = pig_; } public void setCat (String cat_) {cat = ...