Java HashMap race-condition
Ich versuche herauszufinden, wenn es irgendeine race-condition in diesem Stück code. Wenn der Schlüssel nicht " Thread.currentThread', dann würde ich denken, ja. Aber da der thread selbst ist der Schlüssel, wie ist es möglich, eine race-condition? Kein anderer thread kann möglicherweise aktualisieren Sie den gleichen Schlüssel in der HashMap!
public class SessionTracker {
static private final Map<Thread,Session> threadSessionMap = new HashMap<Thread,Session>();
static public Session get() {
return threadSessionMap.get(Thread.currentThread());
}
static public void set(Session s) {
threadSessionMap.put(Thread.currentThread(),s);
}
static public void reset() {
threadSessionMap.remove(Thread.currentThread());
}
}
Beachten Sie, dass es gibt andere Probleme, als die concurrency-Probleme beschrieben, auf die Antworten. Sie können Sichtbarkeit Probleme. (den internen Zustand der Karte, wie gesehen, durch die ein thread werden könnte, unterscheidet sich von den internen Zustand der Karte, wie gesehen, durch einen anderen thread). Wenn Sie anrufen
Trotzdem, die Funktionalität, die Sie suchen, ist genau das, was
set
auf einen thread, und dann, später, ein anderer thread ruft size()
ist, kann es erhalten 0 als Ergebnis.Trotzdem, die Funktionalität, die Sie suchen, ist genau das, was
ThreadLocal
: download.oracle.com/javase/7/docs/api/index.html?java/lang/...InformationsquelleAutor JavaLearner | 2011-10-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Antwort ist ja, es gibt potentielle race conditions:
Besser zu erklären was ich meine auf den zweiten Punkt, ich war auf der Suche an der source-code der HashMap in OpenJdk 7
Zunächst berechnet es einen Hash den Schlüssel (Kombination zweier hash-Funktionen), dann ist es Karten zu einer Zelle mit
indexFor
ist, dann wird überprüft, ob diese Zelle enthält die gleichen Schlüssel oder bereits von einem anderen besetzt. Wenn es die gleichen Schlüssel, es ist nur überschreiben der Wert-und hier gibt es kein problem.Wenn es besetzt sieht er auf die nächste Zelle und dann die nächste, bis er findet eine leere position, und rufen Sie
addEntry()
, die sich sogar entscheiden, um die Größe des array, wenn das array mehr geladen, als eine gewisseloadFactor
.Unserer
table
mit den Einträgen ist einfach nur ein Vektor, derEntry
hält Schlüssel und Wert.In einer konkurrierenden Umgebung, die alle möglichen bösen Dinge passieren können, zum Beispiel ein thread bekommt eine Kollision für die Zelle Nummer 5 und sucht die nächste Zelle (6) und findet es leer.
Inzwischen ein anderer thread bekommt einen index von 6 als Ergebnis der
indexFor
und beide entscheiden zu verwenden, die Zelle in der gleichen Zeit, eine der zwei überschreibt die anderen.besser, aber Lesen der Javadoc. Die zulässige Parallelität bei update-Operationen geführt wird durch die optionale concurrencyLevel argument im Konstruktor (default 16) verwendet wird, das als Hinweis für die interne Dimensionierung. Die Tabelle ist intern partitioniert, um zu versuchen, um zu ermöglichen, angegebenen Anzahl von gleichzeitigen updates, ohne Streit. Da die Platzierung in hash-Tabellen ist im wesentlichen zufällig, die tatsächliche Parallelität variieren.
Hmm, wie wäre es, wenn ich die "HashMap" variable 'threadSessionMap' zu einem 'flüchtigen' variable. Wird, daß die Sperre der gesamten Hashtable?
Nein, nicht durch eine lange erschossen. Beim Umgang mit mehreren threads, die Sie muss "sperren" der Daten-Struktur, oder verwenden Sie eine, die entworfen ist, für die Parallelität. Andernfalls riskieren Sie, die subtilen Fehler, die fast unmöglich zu erkennen und zu verfolgen, Sie für immer...
Sie können die ConcurrentHashMap. Es ist sicher für die Verwendung durch mehrere threads. Das Zitat oben sollte nicht entmutigen: es sagt nur, dass ConcurrentHashMap bietet eine Konfigurations-parameter für verbessern auf die Parallelität -- das ist, mit der Standard-Konfiguration können Sie haben 100, 1000, so viele threads wie du willst Zugriff auf Sie Zug um Zug. Die Sache ist, dass es einige Konflikte (einige threads blockiert werden).Wenn Sie halten Sie unter concurrencyLevel threads, es gibt eine Möglichkeit, dass kein thread jemals zu blockieren, die Verbesserung der Leistung.Es funktioniert in jedem Fall
InformationsquelleAutor stivlo
Ohne sich in spezielle Einzelheiten der Hashmap-Implementierungen, würde ich sagen, dass es immer noch die Möglichkeit, ein Fehler, angesichts der Tatsache, dass die Hashmap-Klasse ist nicht sicher für den gleichzeitigen Zugriff.
Während ich damit einverstanden, dass es nur 1 änderung einer einzigen Schlüssel in einer Zeit, da Sie mit currentThread(), gibt es noch die Möglichkeit, dass mehrere threads Bearbeiten der Hashmap gleichzeitig. Wenn man sich an die konkrete Umsetzung, sollten Sie nicht davon ausgehen, dass nur der gleichzeitige Zugriff auf die gleichen Schlüssel würde zu einem problem führen, auf die Hashmap, und, dass die gleichzeitige änderung auf den verschiedenen Tasten nicht wäre.
Stellen Sie sich einen Fall, wo zwei verschiedene Schlüssel generieren, die denselben hash-Wert, und es ist leicht zu sehen, dass es noch Fehler mit der gleichzeitigen änderung.
InformationsquelleAutor Steven Mastandrea
Ja, das ist nicht eine sichere Sache zu tun (wie die anderen Antworten schon zeigen). Eine bessere Lösung, ganz möglicherweise die Verwendung einer ThreadLocal, die eine mehr Natürliche Weise zu halten thread-lokale Daten als mit einer Karte. Es hat ein paar nette features, einschließlich Standard-Werte und die Werte werden gelöscht, wenn ein thread beendet wird.
Es sieht aus wie Sie versuchen zu assoziieren einer Sitzung mit einem bestimmten Thema. ThreadLocal bietet diese Art von Speicher zu einem thread. So könnte man verwenden, um die Sitzung an den thread angefügt, der ihn besitzt.
InformationsquelleAutor Steven Schlansker
Laut Artikel geschrieben von Pierre Hugues, wenn Sie teilen hashmap zwischen mehreren threads, Ihr Prozess hängen, und Essen alle Ihre cpu-Ressourcen durch unendliche Schleife.
InformationsquelleAutor okwap
Ich Stimme mit den vorherigen Antworten, dass Ihr code ist nicht thread-sicher, und während Sie mit ConcurrentHashMap würde Ihr problem lösen, ist dies der perfekte Fall für ThreadLocal.
Einer kurzen Einführung für ThreadLocal:
ThreadLocal-intern eine andere Instanz von einer Klasse für jeden thread, der greift auf die ThreadLocal, dafür die Lösung concurrency-Probleme. Zusätzlich (je nach situation könnte dies gut/schlecht), der gespeicherte Wert in einem ThreadLocal kann nur zugegriffen werden, indem der thread, aufgefüllt, dass der Wert in den ersten Platz. Wenn es das erste mal auf den aktuellen thread zugreifen wird ThreadLocal, wird der Wert null.
Einfaches Beispiel von ThreadLocal, enthält String-Werte:
InformationsquelleAutor stikku