Win32 Lese- / Schreibsperre mit nur kritischen Abschnitten

8

Ich muss eine Lese- / Schreibsperre in C ++ implementieren, indem ich Win32 api als Teil eines Projekts bei der Arbeit benutze. Alle vorhandenen Lösungen verwenden Kernel-Objekte (Semaphore und Mutexe), die während der Ausführung einen Kontextwechsel erfordern. Das ist viel zu langsam für meine Anwendung.

Ich möchte, wenn möglich, nur eine mit kritischen Abschnitten implementieren. Das Schloss muss nicht prozesssicher sein, nur threadsafe. Irgendwelche Ideen, wie man das macht?

    
Dan Lorenc 17.06.2009, 18:17
quelle

10 Antworten

6

Ich denke nicht, dass dies ohne die Verwendung mindestens eines Kernel-Level-Objekts (Mutex oder Semaphore) möglich ist, weil Sie die Hilfe des Kernels benötigen, um den aufrufenden Prozessblock zu blockieren, bis die Sperre verfügbar ist.

Kritische Abschnitte bieten Blockierung, aber die API ist zu begrenzt. z.B. Sie können keine CS abrufen, erkennen, dass eine Lesesperre verfügbar ist, aber keine Schreibsperre, und warten, bis der andere Prozess den Lesevorgang beendet hat (denn wenn der andere Prozess den kritischen Abschnitt hat, blockiert er andere Leser, und wenn ja dann blockiert Ihr Prozess nicht, sondern dreht sich, CPU-Zyklen werden gebrannt.)

Sie können jedoch eine Drehsperre verwenden und bei Konflikten auf einen Mutex zurückgreifen. Der kritische Abschnitt ist selbst auf diese Weise implementiert. Ich würde eine vorhandene Implementierung des kritischen Abschnitts nehmen und das PID-Feld mit getrenntem Leser u. Schreiber zählt.

    
finnw 17.06.2009, 18:51
quelle
11

Wenn Sie Vista oder höher als Ziel verwenden können, sollten Sie das integrierte SRWLock verwenden . Sie sind leichtgewichtig wie kritische Abschnitte, vollständig benutzerdefiniert, wenn keine Konflikte auftreten.

Joe Duffys Blog enthält einige Einträge zur Implementierung verschiedener Arten von Nicht-Blocking Leser / Schreiber-Sperren. Diese Schlösser drehen sich, also wären sie nicht angebracht, wenn Sie viel Arbeit machen wollen, während Sie das Schloss halten. Der Code ist C #, sollte aber problemlos auf native portiert werden können.

Sie können eine Lese- / Schreibsperre mit kritischen Abschnitten und Ereignissen implementieren - Sie müssen nur genügend Status beibehalten, um das Ereignis nur zu signalisieren, wenn dies erforderlich ist, um einen unnötigen Kernel-Modus-Aufruf zu vermeiden.

    
Michael 17.06.2009 18:47
quelle
6

Alte Frage, aber das sollte etwas funktionieren. Es dreht sich nicht bei Konflikten. Leser haben begrenzte zusätzliche Kosten, wenn sie wenig oder keine Konflikte haben, weil SetEvent träge genannt wird (sehen Sie sich den Bearbeitungsverlauf für eine schwerere Version an, die diese Optimierung nicht hat).

%Vor%

Sie könnten die Kosten für Leser senken, indem Sie ein einzelnes CRITICAL_SECTION verwenden:

  • countsLock wird durch writerLock in rdlock und rdunlock

  • ersetzt
  • rwlock->waitingWriter = FALSE wird in wrunlock entfernt

  • wrlocks Körper wird in

    geändert %Vor%

Allerdings verliert dies an Fairness, daher bevorzuge ich die obige Lösung.

    
Paolo Bonzini 18.10.2010 14:47
quelle
3

Sehen Sie sich das Buch " Concurrent Programming on Windows " an, das viele verschiedene Referenzbeispiele für den Leser enthält / Writer-Sperren.

    
Paul Alexander 17.06.2009 18:26
quelle
3

Schau dir die spin_rw_mutex von Intels Thread-Building-Blöcken ...

  

spin_rw_mutex befindet sich ausschließlich im Benutzerland   und verwendet Spin-Wait zum Blockieren

    
JP Alioto 17.06.2009 18:29
quelle
1

Das ist eine alte Frage, aber vielleicht wird jemand das nützlich finden. Wir haben ein leistungsstarkes Open-Source-Programm RWLock für Windows entwickelt, das automatisch Vista + SRWLock Michael erwähnt , falls verfügbar, oder auf eine Userspace-Implementierung zurückgreift.

Als zusätzlichen Bonus gibt es vier verschiedene "Geschmacksrichtungen" (obwohl Sie sich an die Basis halten können, die auch die schnellste ist), die jeweils mehr Synchronisierungsoptionen bietet. Es beginnt mit der Basis RWLock() , die nicht reentrant ist, beschränkt auf Einzelprozesssynchronisation, und kein Vertauschen von Lese- / Schreibsperren zu einem vollwertigen prozessübergreifenden IPC RWLock mit Wiedereinstiegsunterstützung und Lese- / Schreibzugriff Höhe.

Wie bereits erwähnt, werden sie dynamisch zu den schlanken Lese- / Schreibsperren von Vista + ausgewechselt, um die bestmögliche Leistung zu erzielen, aber Sie müssen sich darüber keine Gedanken machen, da sie auf eine vollständig kompatible Implementierung unter Windows zurückgreift XP und seine Art.

    
Mahmoud Al-Qudsi 25.10.2012 00:48
quelle
0

Wenn Sie bereits von einer Lösung wissen, dass only Mutexe verwendet, sollten Sie sie ändern können, um stattdessen kritische Abschnitte zu verwenden.

Wir rollten unsere eigenen mit zwei kritischen Abschnitten und einigen Zählern. Es passt zu unseren Bedürfnissen - wir haben eine sehr niedrige Autorenzahl, Autoren haben Vorrang vor Lesern usw. Ich bin nicht in der Lage, unsere zu veröffentlichen, kann aber sagen, dass es ohne Mutexe und Semaphoren möglich ist.

    
sean e 17.06.2009 18:23
quelle
0

Hier ist die kleinste Lösung, die ich mir vorstellen konnte:

Ссылка

Und wörtlich eingefügt:

%Vor%     
Ben Harper 06.07.2010 15:12
quelle
0

Schauen Sie sich meine Implementierung hier an:

Ссылка

VRWLock ist eine C ++ - Klasse, die die Logik für einzelne Schreiber - mehrere Leser implementiert.

Sehen Sie sich auch das Testprojekt TestLock.sln an.

UPD. Unten ist der einfache Code für Leser und Schreiber:

%Vor%

Die VRWLock-Klasse unterstützt Spin Count und Thread-spezifische Referenzzählung, die es ermöglicht, Sperren von abgeschlossenen Threads freizugeben.

    
Vitaly 23.12.2013 16:31
quelle
0

Ich habe den folgenden Code nur mit kritischen Abschnitten geschrieben.

%Vor%

Um eine Warteschleife durchzuführen, kommentieren Sie die Zeilen mit Sleep (0).

    
jesusdario 23.01.2015 19:55
quelle