Java mulithreading - Gibt es eine Möglichkeit zu synchonize / einem bestimmten Wert in einer Karte sperrt für Lese- und Schreibvorgänge?

antonig:

Ich wünsche einen Topo-Sortieralgorithmus zu implementieren , die parallel über ein Diagramm in Java unter Verwendung von Threads durchgeführt werden können. Insbesondere fand der Algorithmus dieses Papier in hier .

Der wichtige Teil dieses Algorithmus für diese Frage ist, dass der Zeitplan Wert, den wir für jeden Knoten zu speichern sind, wird wie folgt aktualisiert: wenn ein Faden durch einen Knoten in dem Graph kommt, wird es seinen aktuellen Wert lesen. Wenn der Faden einen höheren Wert hat, wird sie ersetzen und weiter entlang. Sonst wird es dort anhalten.

Ich muss in der Lage, die Schreib- und Lese für einen bestimmten Knoten in einer atomaren Operation zu tun. Ich möchte, den Wert als Wert in einer Karte gegen eine int Schlüssel-ID repräsentieren (für jeden Knoten). Doch von dem, was ich die Synchronisationstechniken für Karten in Java zu sehen scheinen entweder nur beim Schreiben zu sperren, oder die ganze Karte sperren. Wenn die ganze Karte gesperrt ist, Leistung und kann Single-Threaded sein. Wenn der liest nicht gesperrt ist, kann ich das falsche Verhalten bekommen.

Mein Ziel ist es nur auf einem bestimmten Index zu sperren. Wenn zwei Threads verschiedene Knoten lesen und aktualisieren möchten, das ist in Ordnung, aber wenn zwei Threads über den gleichen Knoten kommen, muss ich sicherstellen , dass jeder Betrieb von read -> check -> update or stopatomar geschieht. Der spezifische Fall , dass ich zu vermeiden suchen ist:

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

stattdessen, ich suche zu tun:

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 :

Wenn Ihr Keyset statisch ist , dann können Sie einfach verwenden AtomicIntegerWerte. Sie könnten verwenden compareAndSetwie folgt aus :

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;
    }
}

Alternativ können Sie eine verwenden , ConcurrentHashMapdie nicht die gesamte Karte nicht sperren. Java 8 hinzugefügt , die eine Menge von Gleichzeitigkeit Methoden machen , was Sie relativ einfach wollen. Wenn Ihr Trigger - Code relativ schnell ist beispielsweise dann können Sie einfach verwenden compute():

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

Natürlich können Sie immer einen Wert, die Paare Ihrer Konstruktion intmit einem Schloss, aber das ist für die Schule Arbeit nur nützlich. In der Praxis Schlösser sind so teuer , Sie definitiv nicht wollen , dass jeder in Ihren inneren Schleifen.

Ich denke du magst

Origin http://43.154.161.224:23101/article/api/json?id=207837&siteId=1
Empfohlen
Rangfolge