Heim >Java >javaLernprogramm >Lernen Sie Java-Parallelität: Sperrenoptimierung, ConcurrentHashMap, Sperrentrennung
Einige Vorschläge zur Verbesserung der Sperrleistung
Reduzieren Sie die Sperrleistung Die Zeit
wird nur bei Bedarf synchronisiert, wodurch die Haltezeit der Sperre erheblich verkürzt, die Möglichkeit von Sperrkonflikten verringert und die Parallelitätsfähigkeiten verbessert werden
Verwenden Sie beispielsweise die Synchronisierungssperre „Synchronisieren“. Versuchen Sie, es hinzuzufügen, wenn das Objekt den Variablenstatus teilen muss. Anstatt blind vor der gesamten Methode eine Synchronisierung hinzuzufügen, sperren Sie das Objekt, das diese Methode aufruft, direkt, was die Wahrscheinlichkeit eines Sperrenwettbewerbs erhöht
Ich habe über die Verwendung der ReadWriteLock-Lese-/Schreibtrennung gesprochen, um die Effizienz zu verbessern
Eine Erweiterung ist die Sperrentrennungsstrategie
Um exklusive Sperren zu trennen Ein typisches Referenzszenario für diese Technologie ist die Aufgabenwarteschlange LinkedBlockingQueue. Wie bereits erwähnt, handelt es sich um eine unbegrenzte Aufgabenwarteschlange, die auf der Grundlage einer verknüpften Liste implementiert wird Die Warteschlange ist jeweils komplementär, sodass in der JDK-Implementierung zwei Sperren für diese beiden Operationen bereitgestellt werden.
Wenn Multithreads beispielsweise die put()-Operation ausführen, müssen sie dies am meisten tun konkurrieren um putLock, und die Take-Operation konkurriert um takeLock
/** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();
Sperren, die kontinuierlich dieselbe Ressource beantragt und freigegeben haben, können in eine einmalige Anfrage integriert werden für die Sperre, wodurch der Verbrauch von Anwendungs- und Freigabeaktionen reduziert wird.
Zum Beispiel:
for(int i=0;i<n;i++){ synchronized(lock){} }
ist auf
synchronized(lock){ for(int i=0;i<n;i++){} }
Ein typisches Anwendungsszenario dieser Technologie ist die Implementierung von ConcurrentHashMap. Im Vergleich zu HashMap ist es threadsicher und im Vergleich zu HashTable ist es eine effiziente Parallelität
Es gibt einen großen Unterschied zwischen der Implementierung von ConcurrentHashMap in jdk1.7 und jdk1.8
Die zugrunde liegende Struktur von ConcurrentHashMap ist ein Segment-Array. Die Standardgröße beträgt 16. Jedes Segment-Array kann als kleine HashMap betrachtet werden, was bedeutet, dass das Segment-Array mithilfe einer verknüpften Liste und implementiert wird ein Array.
Wenn wir beispielsweise ein neues Schlüssel-Wert-Paar in die Karte einfügen müssen, finden wir zunächst anhand des Hashcodes des Schlüssels heraus, in welches Segment es eingefügt werden soll, und dann Sperren Sie dieses Segment, um den Put-Vorgang abzuschließen, da die Segmentklasse von der ReentrantLock-Klasse erbt. Beim Erwerb der Sperre verwenden Sie die Sperre nicht direkt, um sie zu erhalten Die Methode bleibt hängen, wenn sie die Sperre nicht erhalten kann. Tatsächlich wird Spin Lock verwendet. Wenn tryLock die Sperre nicht erhalten kann, bedeutet dies, dass die Sperre zu diesem Zeitpunkt durch tryLock erneut angewendet wird. Beim Multithreading kann also echte Parallelität zwischen Threads erreicht werden, solange sich die eingefügten Daten nicht in einem Segment befinden und die Sperrkonkurrenz keine Blockierung verursacht.
Problem: Wenn segmentübergreifende Vorgänge erforderlich sind, d Sperren aller Segmente. Beispielsweise erfordert die size()-Methode von ConcurrentHashMap die Sperre aller UntersegmenteEs ist wichtig zu beachten, dass der Grund, warum jedes Array einen Zähler enthält, anstatt einen globalen Zähler in ConcurrentHashMap zu verwenden, darin besteht, die Parallelität von ConcurrentHashMap zu berücksichtigen: Weil dies der Fall ist Wenn Sie aktualisieren müssen Wenn Sie den Zähler verwenden, müssen Sie nicht die gesamte ConcurrentHashMap sperren.Es ist wichtig zu beachten, dass die Anzahl flüchtig ist, sodass alle Aktualisierungen der Anzahl sofort für andere Threads sichtbar sind.
Verwandte Artikel :
Java-Framework Bootstrap, jQuery, SpringMVC, Hibernate, hohe Leistung und hohe Parallelität
Lösung für Probleme mit hoher Parallelität im Java-System
Ähnliche Videos:
Das obige ist der detaillierte Inhalt vonLernen Sie Java-Parallelität: Sperrenoptimierung, ConcurrentHashMap, Sperrentrennung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!