Beispiel für boost shared_mutex (mehrere Lesevorgänge/ein Schreibvorgang)?

Lesezeit: 7 Minuten

Beispiel fur boost shared mutex mehrere Lesevorgangeein Schreibvorgang
Kevin42

Ich habe eine Multithread-App, die einige Daten häufig lesen muss, und gelegentlich werden diese Daten aktualisiert. Im Moment hält ein Mutex den Zugriff auf diese Daten sicher, aber es ist teuer, weil ich möchte, dass mehrere Threads gleichzeitig lesen können und sie nur sperren, wenn ein Update erforderlich ist (der Aktualisierungsthread könnte warten, bis die anderen Threads fertig sind). .

Ich denke, das ist was boost::shared_mutex soll tun, aber ich bin mir nicht sicher, wie ich es verwenden soll, und habe kein klares Beispiel gefunden.

Hat jemand ein einfaches Beispiel, mit dem ich anfangen könnte?

  • Das Beispiel von 1800 INFORMATION ist korrekt. Siehe auch diesen Artikel: Was ist neu in Boost-Threads.

    – Assaf Lavie

    13. Juni 2009 um 3:52 Uhr

  • mögliches Duplikat von Reader/Writer Locks in C++

    – chao

    23. Juni 2011 um 7:25 Uhr

1646957408 621 Beispiel fur boost shared mutex mehrere Lesevorgangeein Schreibvorgang
mmocny

1800 INFORMATION ist mehr oder weniger korrekt, aber es gibt ein paar Probleme, die ich korrigieren wollte.

boost::shared_mutex _access;
void reader()
{
  boost::shared_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access
}

void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }

  // do more work here, without anyone having exclusive access
}

void unconditional_writer()
{
  boost::unique_lock< boost::shared_mutex > lock(_access);
  // do work here, with exclusive access
}

Beachten Sie auch, dass im Gegensatz zu einem shared_lock nur ein einzelner Thread gleichzeitig ein upgrade_lock erwerben kann, selbst wenn es nicht aktualisiert wird (was ich als unangenehm empfand, als ich darauf stieß). Wenn also alle Ihre Leser bedingte Schreiber sind, müssen Sie eine andere Lösung finden.

  • Nur um “eine andere Lösung” zu kommentieren. Wenn alle meine Leser bedingte Schreiber waren, ließ ich sie immer ein shared_lock erwerben, und wenn ich ein Upgrade zum Schreiben von Privilegien benötigte, würde ich die Lesersperre .unlock() und ein neues unique_lock erwerben. Dies wird die Logik Ihrer Anwendung verkomplizieren, und es gibt jetzt ein Zeitfenster für andere Autoren, den Status zu ändern, nachdem Sie ihn zum ersten Mal gelesen haben.

    – mmocny

    4. März 2011 um 21:30 Uhr


  • Sollte die Linie nicht boost::unique_lock< boost::shared_mutex > lock(lock); lesen boost::unique_lock< boost::shared_mutex > lock( _betreten ); ?

    – SteveWilkinson

    1. April 2011 um 17:01 Uhr


  • Dieser letzte Vorbehalt ist sehr seltsam. Wenn jeweils nur ein Thread eine upgrade_lock halten kann, was ist dann der Unterschied zwischen einer upgrade_lock und einer unique_lock?

    – Ken Smith

    11. August 2011 um 0:11 Uhr

  • @Ken Ich war nicht sehr klar, aber der Vorteil von upgrade_lock ist, dass es nicht blockiert, wenn derzeit einige shared_locks erworben werden (zumindest nicht, bis Sie auf unique upgraden). Der zweite Thread, der versucht, eine upgrade_lock zu erwerben, wird jedoch blockiert, selbst wenn der erste nicht auf unique aktualisiert wurde, was ich nicht erwartet hatte.

    – mmocny

    15. September 2011 um 16:57 Uhr

  • Dies ist ein bekanntes Boost-Problem. Es scheint bei Boost 1.50 Beta gelöst zu sein: svn.boost.org/trac/boost/ticket/5516

    – Ofek Schilon

    26. Juni 2012 um 9:31 Uhr

Beispiel fur boost shared mutex mehrere Lesevorgangeein Schreibvorgang
1800 INFORMATIONEN

Es sieht so aus, als würdest du so etwas tun:

boost::shared_mutex _access;
void reader()
{
  // get shared access
  boost::shared_lock<boost::shared_mutex> lock(_access);

  // now we have shared access
}

void writer()
{
  // get upgradable access
  boost::upgrade_lock<boost::shared_mutex> lock(_access);

  // get exclusive access
  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
  // now we have exclusive access
}

  • Dies ist das erste Mal, dass ich boost verwende, und ich bin ein C++-Neuling, also fehlt mir vielleicht etwas – aber in meinem eigenen Code musste ich den Typ angeben, etwa so: boost::shared_lock lock (_betreten);

    – Ken Smith

    16. März 2010 um 23:02 Uhr

  • Ich versuche, dies selbst zu verwenden, aber ich erhalte eine Fehlermeldung. fehlende Template-Argumente vor ‘lock’. Irgendwelche Ideen?

    – Hookenz

    18. August 2010 um 2:56 Uhr

  • @shaz Diese sind begrenzt, aber Sie können sie bei Bedarf mit .unlock() vorzeitig freigeben.

    – mmocny

    27. Januar 2011 um 18:23 Uhr

  • Ich habe die fehlenden Template-Argumente hinzugefügt.

    Benutzer283145

    7. November 2012 um 22:49 Uhr

  • @raaj Sie können die upgrade_lock erhalten, aber das Upgrade auf eine eindeutige Sperre wird blockiert, bis die shared_lock freigegeben wird

    – 1800 INFORMATIONEN

    10. April 2016 um 21:27 Uhr

1646957409 916 Beispiel fur boost shared mutex mehrere Lesevorgangeein Schreibvorgang
Yocha Timmer

Seit C++ 17 (VS2015) können Sie den Standard für Lese-Schreib-Sperren verwenden:

#include <shared_mutex>

typedef std::shared_mutex Lock;
typedef std::unique_lock< Lock > WriteLock;
typedef std::shared_lock< Lock > ReadLock;

Lock myLock;


void ReadFunction()
{
    ReadLock r_lock(myLock);
    //Do reader stuff
}

void WriteFunction()
{
     WriteLock w_lock(myLock);
     //Do writer stuff
}

Für ältere Versionen können Sie boost mit derselben Syntax verwenden:

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock >  WriteLock;
typedef boost::shared_lock< Lock >  ReadLock;

  • würde ich auch sagen typedef boost::unique_lock< Lock > WriteLock; typedef boost::shared_lock< Lock > ReadLock;.

    – Reben

    17. Januar 2012 um 2:11 Uhr

  • Sie müssen nicht die gesamte Datei thread.hpp einschließen. Wenn Sie nur die Schlösser benötigen, fügen Sie die Schlösser hinzu. Es ist keine interne Implementierung. Beschränken Sie die Includes auf das Minimum.

    – Yochai Timmer

    15. Februar 2014 um 17:55 Uhr

  • Auf jeden Fall die einfachste Implementierung, aber ich denke, es ist verwirrend, sowohl Mutexe als auch Sperren als Sperren zu bezeichnen. Ein Mutex ist ein Mutex, eine Sperre ist etwas, das es in einem gesperrten Zustand hält.

    – Tim MB

    13. Juli 2015 um 14:45 Uhr

Verwenden Sie ein Semaphor mit einer Anzahl, die gleich der Anzahl der Leser ist. Lassen Sie jeden Leser die Semaphore einmal zählen, um zu lesen, damit alle gleichzeitig lesen können. Lassen Sie dann den Schreiber vor dem Schreiben ALLE Semaphor-Zählungen vornehmen. Dies führt dazu, dass der Writer wartet, bis alle Lesevorgänge abgeschlossen sind, und dann Lesevorgänge während des Schreibens blockiert.

  • Die Terekhov algorithm sorgt dafür, dass in 1., der Schriftsteller kann die Leser nicht aushungern. Sieh dir das an. Aber 2. ist wahr. Ein upgrade_lock garantiert keine Fairness. Sieh dir das an.

    – Jonas Vautherin

    14. Februar 2014 um 14:50 Uhr

Beispiel fur boost shared mutex mehrere Lesevorgangeein Schreibvorgang
dale1209

Tolle Antwort von Jim Morris, ich bin darüber gestolpert und es hat eine Weile gedauert, bis ich es herausgefunden habe. Hier ist ein einfacher Code, der zeigt, dass nach dem Absenden einer “Anfrage” für einen Unique_lock-Boost (Version 1.54) alle Shared_lock-Anfragen blockiert werden. Dies ist sehr interessant, da es mir scheint, dass die Wahl zwischen unique_lock und upgradeable_lock erlaubt, ob wir Schreibpriorität oder keine Priorität wollen.

Auch (1) in Jim Morris’ Beitrag scheint dem zu widersprechen: Boost shared_lock. Bevorzugt lesen?

#include <iostream>
#include <boost/thread.hpp>

using namespace std;

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > UniqueLock;
typedef boost::shared_lock< Lock > SharedLock;

Lock tempLock;

void main2() {
    cout << "10" << endl;
    UniqueLock lock2(tempLock); // (2) queue for a unique lock
    cout << "11" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    lock2.unlock();
}

void main() {
    cout << "1" << endl;
    SharedLock lock1(tempLock); // (1) aquire a shared lock
    cout << "2" << endl;
    boost::thread tempThread(main2);
    cout << "3" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(3));
    cout << "4" << endl;
    SharedLock lock3(tempLock); // (3) try getting antoher shared lock, deadlock here
    cout << "5" << endl;
    lock1.unlock();
    lock3.unlock();
}

  • Ich habe tatsächlich Probleme herauszufinden, warum der obige Code Deadlocks verursacht, während der Code eingeht [stackoverflow.com/questions/12082405/… works.

    – dale1209

    Nov 20, 2013 at 22:00

  • It actually deadlocks in (2), not in (3), because (2) is waiting for (1) to release its lock. Remember: to get a unique lock, you need to wait for all the existing shared locks to finish.

    – JonasVautherin

    Feb 14, 2014 at 14:56

  • @JonesV, even if (2) waits for all shared locks to finish, it wouldn’t be a deadlock because it’s a different thread than the one which acquired (1), if line (3) didn’t exist, the program would finish with no deadlocks.

    – SagiLow

    Jul 5, 2017 at 12:11

  • I’m actually having trouble figuring out why the above code deadlocks while the code in [stackoverflow.com/questions/12082405/… works.

    – dale1209

    Nov 20, 2013 at 22:00

  • It actually deadlocks in (2), not in (3), because (2) is waiting for (1) to release its lock. Remember: to get a unique lock, you need to wait for all the existing shared locks to finish.

    – JonasVautherin

    Feb 14, 2014 at 14:56

  • @JonesV, even if (2) waits for all shared locks to finish, it wouldn’t be a deadlock because it’s a different thread than the one which acquired (1), if line (3) didn’t exist, the program would finish with no deadlocks.

    – SagiLow

    Jul 5, 2017 at 12:11

989350cookie-checkBeispiel für boost shared_mutex (mehrere Lesevorgänge/ein Schreibvorgang)?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy