Frage

Bei den meisten gängigen Plattformen (die wichtigsten sind x86; Ich verstehe, dass einige Plattformen extrem schwierig Speichermodelle haben, die so gut wie keine Garantien bieten, die für Multithreading, aber ich kümmere mich nicht um seltene Gegenbeispiele), ist der folgende Code sicher?

Gewinde 1:

someVariable = doStuff();
atomicSet(stuffDoneFlag, 1);

Thread 2:

while(!atomicRead(stuffDoneFlag)) {}  // Wait for stuffDoneFlag to be set.
doMoreStuff(someVariable);

Unter der Annahme, Standard, vernünftige Implementierungen von Atom-ops:

  1. Ist Thread 1 die Zuordnung garantiert someVariable vor atomicSet() abzuschließen genannt wird?
  2. Ist Thread 2 garantiert die Zuordnung sehen someVariable vor dem Aufruf von doMoreStuff() vorausgesetzt, es liest stuffDoneFlag atomar?

Edits:

  1. Die Umsetzung der Atom ops Ich verwende enthält die x86 LOCK Befehl in jedem Betrieb, ob das hilft.
  2. Nehmen wir stuffDoneFlag richtig irgendwie gelöscht wird. Wie ist nicht wichtig.
  3. Dies ist ein sehr vereinfachtes Beispiel. Ich habe es auf diese Weise, so dass Sie nicht den ganzen Kontext des Problems verstehen, müßten sie zu beantworten. Ich weiß, es ist nicht effizient.
War es hilfreich?

Lösung

Wenn Ihr tatsächlicher x86-Code Shop hat vor dem Laden in atomicSet in Thread 1 und Belastung von somevariable nach der Belastung in atomicRead zu somevariable in Thread 2, dann sollten Sie in Ordnung sein. Intel Manual Volume 3A Software-Entwickler für x86 in Abschnitt 8.2 das Speichermodell angibt und die Intra-Fadenspeicher-Speicher- und Ladelastbeschränkungen sollen hier ausreichen.

Es kann jedoch nicht alles, was Ihren Compiler aus Umordnung der Anweisungen von was auch immer höheren Ebene Sprache erzeugt verhindert werden Sie über die atomaren Operationen verwenden.

Andere Tipps

1) Ja

2) Ja

Beide arbeiten.

sieht Dieser Code Thread-sicher, aber ich frage die Effizienz Ihrer spinlock (die während Schleife), wenn Sie nur für eine sehr kurze Zeit zu drehen. Es gibt keine Garantie auf jedem System, das Thread 2 nicht vollständig alle Bearbeitungszeit Schwein.

würde ich mit einigen aktuellen Synchronisierungsgrund empfehlen (sieht aus wie boost :: condition_variable ist, was Sie hier wollen) stattdessen auf dem Spin-Lock zu verlassen.

Die atomaren Anweisungen sicherzustellen, dass der Thread 2 wartet auf Thread 1 die Variable vor dem Faden 2 Erlös Einstellung abzuschließen. Es gibt jedoch zwei zentrale Themen:

1) die someVariable muss ‚deklariert werden volatile ‘, um sicherzustellen, dass die Compiler optimieren nicht, es ist Zuordnung zB Speicherung in einem Register oder Aufschieben eines Schreib.

2) der zweite Thread blockiert, während für das Signal wartet (genannt spinlocking ). Ihre Plattform wahrscheinlich bietet viel bessere Verriegelung und Signal primatives und Mechanismen, sondern eine relativ einfache Verbesserung wäre einfach in das Gewinde 2 des sleep() Körper while().

dsimcha geschrieben: „Es sei angenommen stuffDoneFlag richtig irgendwie gelöscht Wie nicht wichtig ist..“ Das ist nicht wahr!

Lassen Sie uns sehen Szenario:

  1. prüft Thread2 die stuffDoneFlag wenn es 1 ist zu lesen beginnen somevariable.
  2. Vor dem Thread2 beenden Sie die Task-Scheduler unterbrechen ihre Aufgabe zu lesen und die Aufgabe, für einige Zeit aussetzen.
  3. Thread1 Zugriff wieder auf den somevariable und den Speicherinhalt ändern.
  4. Task-Scheduler wieder einschalten Thread2 und den Job, aber Speicherinhalt somevariable weiter verändert wird!
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top