2015-05-19 15 views
5

Die Dokumentation der meisten Sammlungen in der Java-Standardbibliothek wie ConcurrentLinkedQueue, ConcurrentLinkedDequeue und ConcurrentSkipListSet mit dem folgenden Haftungsausschluss kommen:Concurrent Sammlung Größe Berechnung

dass Vorsicht, anders als in den meisten Sammlungen ist die Größe Methode nicht ein Dauerbetrieb. Wegen der asynchronen Natur dieser setzt, erfordert die aktuelle Anzahl der Elemente zu bestimmen ein Traversal der Elemente, und so ungenaue Ergebnisse berichten können, wenn diese Sammlung während Traversal modifiziert wird.

Was bedeutet das? Warum können sie keinen Zähler behalten (sagen wir AtomicInteger) und einfach den Wert für Anrufe an size() zurückgeben?

Ist es, weil der Zähler synchronisiert werden müssen und schafft somit eine Drosselstelle?

Als Randbemerkung, ConcurrentHashMap scheint nicht, dieses Problem zu haben. Warum das? Betrachtet man den Quellcode, sieht es so aus, als ob es mehrere Zähler in einem Array verwendet, die bei Aufrufen von size() summiert werden. Um den Engpass zu umgehen oder gibt es einen anderen Grund?

+0

ein Atom Zähler würde auf jeden Fall schlecht sein. – ZhongYu

Antwort

5

eine gemeinsame Ressource verwenden, die Größe zu halten() teuer und ziemlich nutzlos wäre. size() ist wahrscheinlich nicht korrekt, sobald es zurückkehrt, da Sie die Sammlung nicht sperren können, so dass sie zwischen dem Aufrufen und dem Abrufen des Werts wechseln kann.

ConcurentHashMap hat den gleichen Ansatz. Die Größe() kann falsch sein, bevor die Methode zurückgegeben wurde.

+0

Natürlich kann 'size()' nicht vollständig vertrauenswürdig sein, das akzeptiere ich. Aber das Problem, das ich habe, ist die nicht konstanten Kosten, jedes Element in der Sammlung zu durchlaufen, um sie zu zählen. Aber ich denke, ich hatte Recht mit dem Würgepunkt dann? –

+1

@GustavKarlsson Peters erster Satz spricht den Grund wirklich an. Synchronisierung und Cache-Invalidierung wären für den Betrieb einer Warteschlange sehr kostspielig. Ja, du hattest Recht, da wäre bestimmt ein Flaschenhals. Das ist eines der Hauptprobleme bei 'ReentrantReadWriteLock' –