2017-03-09 4 views
1

Ich versuche, einige Zeichenfolgen aus Threads zu ändern (jeder Thread würde seine eigene Zeichenfolge haben), aber alle Zeichenfolgen werden in einem Vektor gespeichert, weil ich in der Lage sein muss, auf sie zuzugreifen, nachdem die Threads ihre Sache erledigt haben.Wie kann ich eine Zeichenfolge aus einem Thread ändern?

Ich habe keine Threads in C++ verwendet, so dass, wenn dies ist eine schreckliche Sache zu tun, alle Vorschläge willkommen :)

Im Grunde das einzige, was das Programm jetzt tut, ist:

  • erstellen einige Gewinde
  • eine Zeichenkette und eine ID für jeden
  • Thread-Funktion modifiziert die Zeichenfolge senden, um die Thread-ID, um es
  • Ende
  • hinzuzufügen

Dies ergibt eine segfault :(

Ist das nur ein schlechter Ansatz? Wie sonst könnte ich das tun?

static const int cores = 8; 

void bmh_t(std::string & resr, int tid){ 
    resr.append(std::to_string(tid)); 
    resr.append(","); 
    return; 
}   

std::vector<std::string> parbmh(std::string text, std::string pat){ 

    std::vector<std::string> distlists; 
    std::thread t[cores]; 
    //Launch a group of threads 
    for (int i = 0; i < cores; ++i) { 
     distlists.push_back(" "); 
     t[i] = std::thread(bmh_t,std::ref(distlists[i]), i); 
    } 

    for (int i = 0; i < cores; ++i) { 
     t[i].join(); 
    } 

    return distlists; 
} 
+5

vorbelegen der Vektor . Pushback kann die Vektorelemente in den meisten Std-Bibliotheken skalieren und verschieben und das ist nicht threadsicher. Sobald die Vektorgröße festgelegt ist, ist sie threadsicher. – doug

+0

Off topic: Werfen Sie einen Blick auf 'std :: future'. – user4581301

Antwort

4

Ihre grundlegende Vorgehensweise ist in Ordnung. Die wichtigste Sache, die Sie beachten müssen, wenn Sie parallelen Code schreiben, ist, dass alle Daten, die zwischen Threads geteilt werden, auf eine sichere Weise gemacht werden. Da Ihr Algorithmus für jeden Thread eine andere Zeichenfolge verwendet, ist dies ein guter Ansatz.

Der Grund für einen Absturz liegt darin, dass Sie push_back auf Ihrem Zeichenfolgenvektor aufrufen, nachdem Sie jedem Thread bereits einen Verweis auf Daten gegeben haben, die im Vektor gespeichert sind. Dies ist ein Problem, da push_back den Vektor vergrößern muss, wenn seine Größe seine Kapazität erreicht. Dieses Wachstum kann die Verweise ungültig machen, die Sie an jeden Thread gesendet haben, sodass sie in den freigegebenen Speicher schreiben.

Die Lösung ist sehr einfach: Stellen Sie vorher sicher, dass Ihr Vektor nicht wachsen muss. Dies kann mit einem Konstruktorargument erreicht werden, das eine anfängliche Anzahl von Elementen angibt; ein Aufruf zur Reservierung(); oder ein Aufruf von resize().

Hier ist eine Implementierung, die nicht abstürzt:

static const int cores = 8; 

void bmh_t(std::string & resr, int tid){ 
    resr.append(std::to_string(tid)); 
    resr.append(","); 
    return; 
} 

std::vector<std::string> parbmh(){ 

    std::vector<std::string> distlists; 
    std::thread t[cores]; 
    distlists.reserve(cores); 

    //Launch a group of threads 
    for (int i = 0; i < cores; ++i) { 
     distlists.push_back(" "); 
     t[i] = std::thread(bmh_t, std::ref(distlists[i]), i); 
    } 

    for (int i = 0; i < cores; ++i) { 
     t[i].join(); 
    } 

    return distlists; 
} 
+1

Bedenken Sie, warum Sie auch einen Vektor verwenden. Sie könnten zum Beispiel einfach ein Array von Strings verwenden, da Sie den Vektor presize müssen. – Donnie

+0

Vielleicht ist es bemerkenswert, dass allding 'std :: vector :: resize()' mit dem aktuellen Code nicht funktioniert, weil 'push_back'. – Galik

+0

@Donnie-Arrays haben zwar eine feste Größe, es sei denn, Sie ordnen sie dynamisch zu und Sie können dann auch einen Vektor verwenden (was dasselbe tut). Auch die Rückgabe eines Arrays ist problematisch. – Galik

1

Der Vektor der Strings wird zerstört, bevor die Threads auf die enthaltenen Strings einwirken können. Sie wollen join die Threads vor dem Zurückgeben, damit der Vektor der Zeichenfolgen nicht zerstört wird.

+0

"zerstört"? Die erste Kopie vielleicht, aber es gibt 'return distlists;', und was ist, wenn OP den Vektor später benutzen will, nachdem 'parbmh' zurückkommt? Ich denke, dass es hier ein schlechtes Design geben kann, aber gibt es genug Informationen? – Aaron

+0

@Aaron Ja, es gibt genug Informationen und die Antwort ist richtig. –

+0

@ πάνταῥεῖ Also, Sie wissen sicher, dass OP distlists nicht zurückgibt, weil er plant, es an anderer Stelle im aktuellen Thread zu verwenden, und OP nicht beabsichtigt, dass der aktuelle Thread ausgeführt wird, während die erzeugten Threads ausgeführt werden? Vielleicht meint er es so. Wenn ich es von Ihrem Standpunkt aus lese, ist das wahrscheinlich sinnvoller. Es ist nicht explizit angegeben, aber ich nehme an, es ist impliziert. – Aaron

Verwandte Themen