Frage

Ich bin ein wenig verwirrt über die richtige Verwendung der kritischen Abschnitte in Multithreading-Anwendungen. In meiner Anwendung gibt es mehrere Objekte (einige Ringpuffer und ein serielles Port-Objekt), zwischen Threads gemeinsam genutzt werden. Sollte den Zugang dieser Objekte immer in kritischen Abschnitten platziert werden, oder nur zu bestimmten Zeiten? Ich vermute, nur zu bestimmten Zeiten, weil, wenn ich jede Verwendung mit einer EnterCriticalSection / LeaveCriticalSection Ich laufe in wickeln versucht, wie es schien eine Deadlock-Bedingung zu sein. Einsicht Sie haben würde geschätzt. Danke.

War es hilfreich?

Lösung

Wenn Sie eine Ressource über Threads gemeinsam nutzen, und einige dieser Themen lesen, während andere schreiben, dann muss es immer geschützt werden.

Es ist schwer, mehr Ratschläge zu geben, ohne mehr über Ihren Code zu kennen, aber hier sind einige allgemeine Punkte im Auge zu behalten.

1) Kritische Abschnitte schützen Ressourcen , nicht Prozesse .

2) Geben Sie / leave kritische Abschnitte in der gleichen Reihenfolge über alle Threads. Wenn Thread A Foo eintritt, tritt dann in Bar, dann B Foo und Bar in der gleichen Reihenfolge eingeben Gewinde muss. Wenn Sie dies nicht tun, könnten Sie ein Rennen erstellen.

3) Ein- und Aussteigen muß in umgekehrter Reihenfolge durchgeführt werden. Beispiel, da Sie Foo trat dann in Bar eingegeben, müssen Sie Bar verlassen, bevor Foo zu verlassen. Wenn Sie dies nicht tun, könnten Sie ein Deadlock erstellen.

4) Halten Schlösser für den kürzesten Zeitraum vernünftigerweise möglich ist. Wenn Sie mit Foo fertig sind, bevor Sie mit Bar beginnen, lassen Sie Foo vor Bar greifen. Aber Sie müssen noch von oben die Ordnungsregeln im Auge behalten. In jedem Thread, dass Anwendungen sowohl Foo und Bar, Sie müssen in der gleichen Reihenfolge erwerben und freigeben:

  Enter Foo
  Use Foo
  Leave Foo
  Enter Bar
  Use Bar
  Leave Bar

5) Wenn Sie nur 99,9% der Zeit und Schreib 0,1% der Zeit lesen, versuchen Sie nicht klug zu sein. Sie haben noch einmal die krit sec einzugeben, wenn Sie nur gerade lesen. Dies liegt daran, dass Sie keine Schreib wollen, wenn your'e in der Mitte einer Lese zu starten.

6) Halten Sie die kritischen Abschnitte körnig. Jeder kritischer Abschnitt sollte eine Ressource schützen, nicht mehr Ressourcen. Wenn Sie die kritischen Abschnitte zu „groß“ machen, könnten Sie Ihre Anwendung serialisiert werden oder eine sehr mysteriöse Gruppe von Deadlocks oder Rassen erstellen.

Andere Tipps

Verwenden Sie eine C ++ Wrapper um den kritischen Abschnitt, die unterstützt RAII:

{
    CriticalSectionLock lock ( mutex_ );

    Do stuff...
}

Der Konstruktor für die Sperre erwirbt den Mutex und der Destruktor gibt den Mutex auch wenn eine Ausnahme ausgelöst wird.

Versuchen Sie nicht zu einem Zeitpunkt mehr mehr als eine Sperre zu gewinnen und versuchen, Funktionen außerhalb der Klasse zu vermeiden, ruft während Schleusen zu halten; dies hilft Schlösser an verschiedenen Orten zu vermeiden gewinnen, so dass Sie neigen dazu, weniger Möglichkeiten für Deadlocks zu bekommen.

Wenn Sie mehr als eine Sperre zur gleichen Zeit gewinnen müssen, sortiert die Schlösser durch ihre Adresse und sich, um zu gewinnen. Auf diese Weise mehr Prozesse gewinnen die gleichen Schlösser in der gleichen Reihenfolge, ohne Koordination.

Mit einem IO-Port, zu prüfen, ob Sie die gleichzeitig als Eingabe Sperre Ausgabe müssen - oft haben Sie einen Fall, wo etwas versucht zu schreiben, erwartet dann zu lesen, oder umgekehrt. Wenn Sie zwei Schlösser haben, dann können Sie eine Sackgasse, wenn ein Thread schreibt dann liest, und der andere liest dann schreibt. Oft ein Gewinde aufweist, die die IO und eine Warteschlange von Anfragen lösen das tut, aber das ist ein wenig komplizierter als nur Verpackung ruft mit Schlössern auf, und ohne viel genauer kann ich es nicht empfehlen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top