Java mulithreading - ¿Hay una manera de sincronizarlas / bloquear un valor específico en un mapa de lecturas y escrituras?

antonig :

Estoy queriendo implementar un algoritmo de topo-tipo que se puede hacer en paralelo sobre un gráfico en Java utilizando hilos. Específicamente, el algoritmo encuentra en este trabajo aquí .

La parte importante de este algoritmo para esta pregunta es que el valor horario estamos almacenando para cada nodo se actualiza de la siguiente manera: si un hilo viene a través de un nodo en el gráfico, se leerá su valor actual. Si el hilo tiene un valor más alto, lo reemplazará y continuará a lo largo. De lo contrario, se detendrá ahí.

Tengo que ser capaz de hacer la escritura y lectura para un nodo específico en una operación atómica. Quiero representar el valor como un valor en un mapa en contra de un identificador de clave int (para cada nodo). Sin embargo, por lo que veo las técnicas de sincronización para Mapas en java parecen bloquear o bien sólo en las escrituras, o bloquear todo el mapa. Si todo el mapa está bloqueado, el rendimiento puede ser también de un solo subproceso. Si las lecturas no están bloqueados, puedo obtener el comportamiento equivocado.

Mi objetivo es bloquear sólo en un índice específico. Si dos hilos quieren leer y actualizar los diferentes nodos, que está bien, pero si dos hilos se encuentran con el mismo nodo, que necesita para asegurarse de que cada operación de read -> check -> update or stoppasa atómicamente. El caso específico Busco a evitar es:

Thread_1 (val 5) read g_1 -> value is 3, trigger update
Thread_2 (val 4) read g_1 -> value is 3, trigger update
Thread_1 (val 5) lock and update g_1 -> g_1 value is 5
Thread_2 (val 4) lock and update g_1 -> g_1 value is 4

en cambio, estoy buscando hacer:

Thread_1 (val 5) lock g_1
Thread_2 (val 4) wait for g_1
Thread_1 (val 5) read g_1 -> value is 3, update g_1 -> g_1 value is 5
Thread_1 (val 5) release g_1
Thread_2 (val 4) lock g_1
Thread_2 (val 4) read g_1 -> value is 5, do nothing
Thread_2 (val 4) release g_1
Adam:

Si su conjunto de claves es estático, entonces puede simplemente utilizar AtomicIntegerlos valores. Se podría utilizar compareAndSetla siguiente manera:

atomicValue = map.get(key);
while (true) {
    value = atomicValue.get();
    if (value < myThreadNumber) {
        if (value.compareAndSet(value, myThreadNumber) {
            // successfully increased the thread number
            triggerUpdate();
            break;
        } // else value update failed, loop back to try again.
    } else {
        break;
    }
}

Alternativamente, se puede utilizar una ConcurrentHashMapque no bloquee todo el mapa. Java 8 añade una gran cantidad de métodos de concurrencia que le hacen lo que quiere relativamente sencillo. Por ejemplo, si su código de activación es relativamente rápido, entonces solo puede utilizar compute():

map.compute(key, (key, value) -> {
    if (value < myThreadNumber) {
        triggerUpdate();
        return myThreadNumber;
    }
    return value; // no changes
})

Por supuesto, siempre se puede construir un tipo de valor que sus pares intcon una cerradura, pero eso es sólo útil para el trabajo escolar. En la práctica, las cerraduras son tan caros que definitivamente no desea ninguna de sus bucles internos.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=207844&siteId=1
Recomendado
Clasificación