2017-10-24 1 views
0

Ich habe zehn generische Funktionen, die alle häufig in meinem Framework laufen. Zwei dieser Funktionen sind vom Typ A, und die anderen acht sind vom Typ B. Ich möchte die Typ-A-Funktionen gleichzeitig ausführen können, aber nicht zulassen, dass die Typ-B-Funktionen ausgeführt werden, wenn die Typ-A-Funktionen ausgeführt werden. Wenn eine Typ-B-Funktion ausgeführt wird, möchte ich nicht, dass eine Typ-A-Funktion ausgeführt wird. Ich möchte auch keinen anderen Typ B laufen lassen, wenn einer bereits läuft.Zwei Funktionen können gleichzeitig ausgeführt werden, aber nicht mit anderen Funktionen

Gibt es eine bessere Möglichkeit, dies zu implementieren (in Java speziell), anders als mit einem ReentrantReadWriteLock, mit den Lesesperren um Typ A und den Schreibsperren um Typ B?

ReentrantReadWriteLock ist für den Fall, dass eine Lesersperre die meiste Zeit benötigt wird und eine Schreibsperre "von Zeit zu Zeit" benötigt wird. In meinem Fall werden jedoch alle Funktionen die ganze Zeit verwendet, was bedeutet, dass die Funktionen alle auf der gleichen Frequenz aufgerufen werden. Ob ich den ReentrantReadWriteLock fair oder unfair mache, sehe ich eine Menge Konflikte zwischen den Sperren in meinem System.

+1

Wenn 'ReentrantReadWriteLock' für Ihre Zwecke passt, warum suchen Sie etwas anderes? Unwahrscheinlich gibt es einen anderen Mechanismus in Java, der das gleiche Verhalten wie 'ReentrantReadWriteLock' hat. Wenn Sie denken, dass rw-lock nicht die Art der Korrelation zwischen A und B widerspiegelt, geben Sie weitere Informationen zu diesen Funktionen an (z. B. ** warum ** können sie nicht gleichzeitig ausgeführt werden). – Tsyvarev

+0

Warum suchen Sie nach einem "besseren" Weg? Was ist falsch an der Verwendung eines 'ReadWriteLock'? Was versuchst du zu "reparieren"? Ist es einfach, dass Sie die Namen nicht mögen, z. Wäre es für Sie besser, wenn sie Exclusive Locks und Shared Locks heißen würden? – Andreas

+0

Siehe Bearbeitungen für weitere Ausführungen –

Antwort

0

ReentrantReadWriteLock ist für den Fall, dass eine Lesersperre die meiste Zeit benötigt wird und eine Schreibsperre "hin und wieder" benötigt wird.

Ich bin mir nicht sicher, wo Sie diese Idee haben. ReentrantReadWriteLock wird in vielen Orten verwendet, um genau die Situation, die Sie skizzieren. Es wurde entwickelt, um hohe Leistung und (natürlich) Reentrant und jede Lösung, die Sie aus manuellen Codierung zusammensetzen könnte höchstwahrscheinlich nicht so gut funktionieren.

aber in meinem Fall, alle Funktionen sind die ganze Zeit verwendet, was bedeutet, dass die Funktionen alle auf der gleichen Frequenz aufgerufen werden.

Dies sollte in Ordnung sein. Sie sollten das Kleingedruckte der um "Fairness" lesen, aber jede Frequenz von A und B wird durch das Schloss gut behandelt werden.

Um die Dokumente im "fairen" Modus zu summieren, blockiert eine B-Aufgabe, um die Schreibsperre zu erhalten, hinter eine Gruppe von A-Aufgaben, die bereits warten. Wenn eine A-Task gesperrt wird, wird sie nur ausgeführt, wenn keine B-Tasks bereits warten. Der "Unfair" -Modus würde es ermöglichen, dass A-Tasks ausgeführt werden und möglicherweise B-Tasks verhungern, wenn sie kontinuierlich kommen, aber "normalerweise einen höheren Durchsatz haben als eine faire Sperre".

Ich würde mit "fairen" Politik bleiben, es sei denn, Sie haben bestimmte Gründe, etwas anderes zu tun.

Ob ich die ReentrantReadWriteLock fair oder unfair mache, sehe ich eine Menge Streit der Sperren in meinem System.

Ich denke, das ist zu erwarten. Egal, welche Lösung Sie haben, wenn Sie A- und B-Tasks mit einer Abstiegsfrequenz ausführen, erhalten Sie Sperrkonflikte. Vielleicht können wir Ihnen bessere Antworten geben, wenn Sie Ihre Frage bearbeitet haben und mehr Details darüber zur Verfügung gestellt haben, warum Sie die Behauptung für unerwartet halten.

Ich möchte die Typ-A-Funktionen gleichzeitig ausführen können, aber nicht zulassen, dass die Typ-B-Funktionen ausgeführt werden, wenn die Typ-A-Funktionen ausgeführt werden.

So würde eine Aufgabe verwendet die Teil der ReentrantReadWriteLock lesen:

private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 
private final Lock readLock = readWriteLock.readLock(); 
private final Lock writeLock = readWriteLock.writeLock(); 
... 
private void functionA() { 
    readLock.lock(); 
    try { 
     // do the A processing here ... 
    } finally { 
     readLock.unlock(); 
    } 
} 

wenn ein Typ-B-Funktion ausgeführt wird, ich will nicht, dass jede Art eine Funktion zu dürfen, Lauf. Ich möchte auch keinen anderen Typ B laufen lassen, wenn einer bereits läuft.

So B Aufgaben würde den Schreibteil des Schlosses verwenden:

private void functionB() { 
    writeLock.lock(); 
    try { 
     // do the B processing here ... 
    } finally { 
     writeLock.unlock(); 
    } 
} 
+0

Ich wollte feststellen, dass der Grund, warum ich nach einer besseren Lösung suchte, ist, dass in der Dokumentation hier https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html "ReentrantReadWriteLocks kann verwendet werden, um die Parallelität bei einigen Arten von Auflistungen zu verbessern. Dies lohnt sich normalerweise nur dann, wenn die Auflistungen groß sein sollen, auf mehr Leser- als auf Autorenthreads zugegriffen wird und Operationen mit Overhead zur Folge haben, die die Synchronisierung überwiegen Overhead. "Vielen Dank für die Erklärung, dass der Streit, den ich erlebt habe, normal war. –

+0

Rechts @ KeyanRhm. Ich vermute, dass die Aussage, die Sie zitieren, versucht, darauf hinzuweisen, dass Sie sich durch die Verwendung dieser Sperre nicht viel vom Overhead des synchronisierten Schlüsselwortes sparen. – Gray

Verwandte Themen