2013-04-26 8 views
6

Vorgeschlagen für die Aufnahme in C++ 14 (alias C++ 1y) sind einige neue Thread-Synchronisations-Primitive: Latches und Barrieren. Der Vorschlag istGibt es im "Latch" -Sample in N3600 eine Racebedingung?

Es klingt wie eine gute Idee, und die Proben sehr Programmierer-freundlich aussehen. Leider denke ich, dass der Beispielcode undefiniertes Verhalten anspricht. Der Vorschlag sagt von latch::~latch():

Zerstört den Riegel. Wenn das Latch zerstört wird, während sich andere Threads in wait() befinden oder count_down() aufrufen, ist das Verhalten undefiniert.

Beachten Sie, dass es heißt "in wait()" und nicht, wie die Beschreibung von count_down() Nutzungen "in wait() blockiert".

Dann wurde die folgende Probe wird zur Verfügung gestellt:

Ein Beispiel des zweiten Anwendungsfall wird unten gezeigt. Wir müssen Daten laden und dann mit einer Anzahl von Threads verarbeiten. Das Laden der Daten ist I/O-gebunden, während das Starten von Threads und das Erstellen von Datenstrukturen CPU-gebunden ist. Indem diese parallel laufen, kann der Durchsatz erhöht werden.

void DoWork() 
{ 
    latch start_latch(1); 
    vector<thread*> workers; 
    for (int i = 0; i < NTHREADS; ++i) { 
     workers.push_back(new thread([&] { 
     // Initialize data structures. This is CPU bound. 
     ... 
     start_latch.wait(); 
     // perform work 
     ... 
     })); 
    } 
    // Load input data. This is I/O bound. 
    ... 
    // Threads can now start processing 
    start_latch.count_down(); 
} 

Gibt es kein Rennen Zustand zwischen den Faden Wachen und der Rückkehr von wait() und Zerstörung des Riegels, wenn es Spielraum läßt? Außerdem sind alle Objekte thread durchgesickert. Wenn der Scheduler nicht alle Worker-Threads ausführt, bevor count_down zurückgegeben wird, und das start_latch-Objekt den Gültigkeitsbereich verlässt, dann führt dies zu einem undefinierten Verhalten. Vermutlich besteht die Lösung darin, den Vektor und join() und delete alle Worker-Threads nach count_down zu wiederholen, aber bevor er zurückkehrt.

  1. Gibt es ein Problem mit dem Beispielcode?
  2. Stimmen Sie zu, dass ein Angebot ein vollständig korrektes Beispiel zeigen sollte, auch wenn die Aufgabe sehr einfach ist, damit die Prüfer sehen können, wie die Nutzungserfahrung aussehen wird?

Hinweis: Es scheint möglich, dass eine oder mehrere der Worker-Threads noch nicht warten begonnen, und deshalb wait() auf einem zerstörten Riegel nennen.


Update: Es gibt jetzt eine neue Version des Angebots, aber das repräsentative Beispiel ist unverändert.

+0

@stefan: Ich glaube nicht, dass „Freigabe der blockierten Threads“ enthält „Warten auf diese Fäden von' Wartezeit zumindest bis zur Rückkehr laufen() '“ –

+0

Darüber hinaus ist es möglich, dass eine der threads hat noch nicht einmal den 'start_latch.wait()' Aufruf erreicht. –

+0

Ich stimme dir zu. Es scheint, dass das Beispiel gebrochen ... – yohjp

Antwort

4

Danke, dass Sie darauf hingewiesen haben. Ja, ich denke, dass der Beispielcode (der in seiner Verteidigung prägnant sein sollte) gebrochen ist. Es sollte wahrscheinlich warten, bis die Threads fertig sind.

Jede Implementierung, die das Blockieren von Threads in wait() erlaubt, wird mit ziemlicher Wahrscheinlichkeit eine Art von Bedingungsvariable enthalten und das Löschen des Latch, während ein Thread wait() noch nicht beendet hat, ist möglicherweise undefiniert.

Ich weiß nicht, ob es Zeit ist, das Papier zu aktualisieren, aber ich kann sicherstellen, dass die nächste Version behoben ist.

Alasdair

+1

Willkommen bei StackOverflow, und danke für die öffentliche Antwort. Es wäre wirklich großartig, wenn Sie mit einem Link zur nächsten Version fortfahren würden, sobald sie verfügbar ist. –

+0

Es gibt ein zusätzliches SG1-Treffen in Santa Clara im Juli - ich habe ein aktuelles Papier zum SG1-Wiki gepostet, und ich würde erwarten, dass es (zusammen mit anderen Änderungen, die aus Santa Clara kommen) im Vor-Chicago veröffentlicht wird Mailing. –