2009-08-07 7 views
22

Ich versuche, eine ziemlich einfache Thread-Anwendung zu schreiben, aber bin neu in der Thread-Bibliothek boost. Ein einfaches Testprogramm arbeite ich an ist:(einfach) boost thread_group Frage

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

int result = 0; 
boost::mutex result_mutex; 

boost::thread_group g; 

void threaded_function(int i) 
{ 
    for(; i < 100000; ++i) {} 

    { 
     boost::mutex::scoped_lock lock(result_mutex); 
     result += i; 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    boost::thread t1(threaded_function, 10); 
    boost::thread t2(threaded_function, 10); 
    boost::thread t3(threaded_function, 10); 

    g.add_thread(&t1); 
    g.add_thread(&t2); 
    g.add_thread(&t3); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 

Allerdings, wenn ich dieses Programm, das ich eine Ausgabe von

$ ./test 
300000 
test: pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed. 
Aborted 

erhalten kompilieren und ausführen Offensichtlich ist das Ergebnis korrekt, aber ich mache mir Sorgen über diese Fehlermeldung, vor allem weil das echte Programm, das im Wesentlichen die gleiche Struktur hat, am Punkt join_all() hängen bleibt. Kann mir jemand erklären, was passiert? Gibt es eine bessere Möglichkeit, dies zu tun, d. H. Eine Anzahl von Threads zu starten, sie in einem externen Container zu speichern und dann darauf zu warten, dass sie alle abgeschlossen sind, bevor das Programm fortgesetzt wird?

Danke für Ihre Hilfe.

Antwort

25

Ich denke, dass Ihr Problem durch den thread_group-Destruktor verursacht wird, der aufgerufen wird, wenn Ihr Programm beendet wird. Die Thread-Gruppe möchte die Zerstörung Ihrer Thread-Objekte übernehmen. Siehe auch in der boost::thread_group Dokumentation.

Sie erstellen Ihre Thread-Objekte im Stapel als lokale Variablen im Bereich Ihrer Hauptfunktion. Daher wurden sie bereits beim Beenden des Programms zerstört und thread_group versucht sie zu löschen.

Als Lösung erstellen Sie Ihre Thread-Objekte auf dem Heap mit neuen und lassen Sie die Pflege ihrer Zerstörung thread_group nehmen:

boost::thread *t1 = new boost::thread(threaded_function, 10); 
... 
g.add_thread(t1); 
... 
+0

Sie sollten die Auslassungszeichen zwischen der "neuen" Speicherzuweisung entfernen und an die thread_group übergeben. Andernfalls, wenn etwas in dem intervenierenden Code schief geht (d. H. Wirft), werden Sie den Thread lecken. –

+0

Ja, das scheint der Fall zu sein und war auch die Ursache für den Fehler im größeren Programm. Das Arbeitsbeispiel verwendet jetzt: // starten Sie drei Threads g.add_thread (neue boost :: thread (thread_function, 10)); g.add_thread (neuer boost :: thread (thread_function, 10)); g.add_thread (neuer boost :: thread (thread_function, 10)); – RandomGuy

+1

Ein guter Weg, um sicherzustellen, dass Sie nicht lecken, wäre es gewesen, std :: unique_ptr oder eine ähnliche Lösung zu verwenden und ptr.get() zu verwenden, um den Thread dem group_thread bereitzustellen. – Klaim

2

add_thread() übernimmt den Besitz des Threads, den Sie übergeben. Thread-Gruppe löscht den Thread. In diesem Beispiel löschen Sie den Speicher, der auf dem Stack zugewiesen wurde, sozusagen einen Kapitalverbrechen.

Mitgliedsfunktion add_thread()

Hohlraum add_thread (Gewinde * thrd);

Voraussetzung:

Der Ausdruck thrd löschen ist gut ausgebildet und wird in undefinierten Verhalten führen.

Effekte:

nehmen den boost :: Thread Objekt, auf das durch thrd und fügen Sie es an die Gruppe.

Nachbedingung:

this-> size() um eins erhöht.

Nicht sicher, ob das in Ihrem Code falsch ist oder ob dies nur ein Beispielfehler ist. Sonst sieht der Code gut aus.

24

Wenn Sie nicht brauchen, ein Handle auf Ihre Fäden, versuchen Sie es mit thread_group :: create_thread(), die die Notwendigkeit mildert den Faden überhaupt zu verwalten:

// Snip: Same as previous examples 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    for (int i = 0; i < 3; ++i) 
     g.create_thread(boost::bind(threaded_function, 10)); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 
+0

create_thread gibt immer noch einen Punkt an den Thread zurück http://www.boost.org/doc/libs/1_39_0/doc/html/thread/thread_management.html#thread.thread_management.threadgroup.create_thread. Der Grund dafür, dass create_thread in diesem Fall verwendet werden kann, liegt darin, dass im Gegensatz zu add_thread die Threadgruppe nicht dafür verantwortlich ist, den Thread zu löschen. – shank22

0

Es sieht keine von oben tatsächlich die Frage beantwortet.

Ich traf das ähnliche Problem. Die Folge dieser Warnung (pthread_mutex_lock.c: 87: __pthread_mutex_lock. Assertion `Mutex -> _ Daten _owner == 0' ist fehlgeschlagen Abgebrochen.) Ist, dass manchmal die Programmthreads undicht wird und eine boost_resource_error Ausnahme verursachen.

Der Grund sieht aus wie das Programm weiterhin nach join_all() ausgeführt wird, obwohl die meisten Threads noch ausgeführt werden (nicht beendet).

Verwandte Themen