Warum ist das ReadWriteLock-Upgrade nicht erlaubt?

9

ReadWriteLock downgrade ist erlaubt von ReentrantReadWriteLock implementation ( tryLock() aus dem Beispiel unten gibt immer true zurück):

%Vor%

Was war die Idee dahinter, ein Lock-Upgrade auf ähnliche Weise nicht zuzulassen? Die tryLock() -Methode für eine Write -Sperre unten könnte true ohne Risiko für einen Deadlock zurückgeben, wenn keine anderen Threads vorhanden sind, die eine Read -Sperre halten:

%Vor%     
Bass 26.10.2015, 09:43
quelle

1 Antwort

2

Zunächst möchten wir darauf hinweisen, dass Upgrade und Downgrade in Bezug auf die semantische Komplexität für ReadWriteLock s nicht äquivalent sind.

Sie müssen keine Konflikte abwehren, um eine Downgrade-Transaktion abzuschließen, da Sie bereits die meisten Eskalationsberechtigungen für die Sperre besitzen und weil Sie garantiert der einzige Thread sind, der derzeit ein Downgrade durchführt. Dasselbe gilt nicht für das Upgrade, daher muss der Mechanismus, der das Upgrade unterstützt, natürlich komplexer (oder viel intelligenter) sein.

Um verwendbar zu sein, muss der Upgrade-Mechanismus Deadlocks verhindern, falls zwei Lese-Threads gleichzeitig versuchen, ein Upgrade durchzuführen (oder speziell für ReentrantReadWriteLock , falls ein einzelner Lese-Thread mit mehreren Lese-Sperren versucht, ein Upgrade durchzuführen). Darüber hinaus muss der Mechanismus angeben, wie die fehlgeschlagene Aktualisierungsanforderung gehandhabt werden soll (wird ihre Lesesperre ungültig gemacht) und das ist noch weniger trivial.

Wie Sie wahrscheinlich schon sehen, ist das vollständige Behandeln dieser Probleme in ReentrantReadWriteLock unbequem, (noch, das ist es, was .NET %Co_de% versucht und ich denke tatsächlich gelingt es). Meine Vermutung ist, dass, während ReaderWriterLock in einigen trivialen Fällen erfolgreich sein könnte, die Upgrade-Fähigkeit für den normalen Gebrauch noch nicht gut genug wäre - unter schwer genug Konkurrenz, wenn Sie das Rennen um die Schreibsperre verlieren, sind Sie im selben Boot, als ob du die Lesesperre entsperrt hättest und versucht hast, die Schreibsperre zu erhalten (was die Möglichkeit für jemanden anderen übrig lässt, hineinzuschleichen und die Schreibsperre dazwischen zu nehmen).

Eine gute Möglichkeit, die Aktualisierbarkeit von Sperren zu ermöglichen, besteht darin, dass nur ein einzelner Thread versucht, ein Upgrade durchzuführen - das ist final boolean writeLockAcquired = readWriteLock.writeLock().tryLock(); tut oder was .NET ReentrantReadWriteUpdateLock tun. Ich würde jedoch immer noch empfehlen% 8_%% von Java 8 als:

  • unter geringen Konkurrenzsituationen sind seine optimistischen Lesevorgänge viel schneller als die Verwendung von Lesesperren
  • seine API ist weit weniger restriktiv bei der Aktualisierung (vom optimistischen Lesen zum Lesen der Sperre in die Schreibsperre)
  • meine verschiedenen Versuche, einen realistischen JMH-Benchmark zu erstellen, bei dem eines der anderen ähnlichen Locks es schlägt, haben fast immer versagt
Dimitar Dimitrov 11.04.2016, 23:09
quelle