2016-04-06 5 views
0

Ich schreibe ein Multithreading-Programm in C++. Im Programm habe ich ein globales Map-Objekt verwendet, das einen pthread_t als Schlüssel und ein Paar als Wert enthält. Das Paar wird nach Wert eingefügt (mithilfe von make_pair). Das Paar enthält eine Liste (nach Wert eingefügt) als erstes Element. Zu dieser Liste möchte ich lesen und schreiben. (Das zweite Element ist pthread_mutex_t.)Liste in C++ ist nicht leer, aber es gibt keine Elemente zum Iterieren

Nun, ich habe Mutex, die ich verwende, um die Leseoperationen & auf der Liste zu steuern. Ich konnte auch sehen, dass das Schieben der Elemente zur Liste erfolgreich war. Wie auch immer, mit der Methode list.empty im Thread, nennen wir es X, konnte ich sehen, dass die Liste nicht leer ist (ohne Mutex, was bei meinem speziellen Design kein Problem darstellt). Daher habe ich den Mutex verwendet, um die Liste zu sperren und die Elemente zu iterieren. Aber - die Iteration ist nicht passiert - so, als ob es keine Elemente in der Liste gäbe.

Hier ist ein Code-Snippest. Übrigens möchte ich pthread_t und keine anderen Optionen verwenden.

Einfügung - Ich überprüfte, es funktioniert: ThreadData & data = threadsOutput [my_key];

data.first.push_back(std::make_pair<Obj1*, Obj2*>(std::move(key),std::move(value))); 

Iterieren: // einige Code zu überprüfen, ob die betreffende Liste

// the list is not empty, so running: 

ThreadData& data = threadsOutput[my_key]; 

if (pthread_mutex_lock(&(data.second))) // data.second is the relevant pthread_mutex_t 

    return; // not arrives here - lock succeeded 


MapResult::iterator it = data.first.begin(); 

for (; it != data.first.end(); ++it) 

{ 

    //some code - not arrives to this code 

} 

Dank leer

ist!

+0

Aus Neugier, was verhindert, dass die Karte zwischen der Zeit, die Sie die Referenz erhalten, und der Zeit, in der Sie den Mutex tatsächlich verriegeln, geändert wird (und damit die Hot-Referenz ungültig wird). – WhozCraig

+0

"check ohne Mutex, was bei meinem speziellen Design kein Problem darstellt" - welches magisches Design könnte es der "leeren" Methode ermöglichen, (a) korrekt zu funktionieren und (b) ein brauchbares Ergebnis zu erhalten, wenn es ohne Call aufgerufen wird der Mutex gehalten? – davmac

+0

ist es nicht beheben dieses Problem - aber der allgemeine Ablauf des Programms funktioniert auf eine Weise, dass, wenn der Thread Daten verpasst (da der Thread falsche Antworten aus dem leeren), diese Daten später behandelt werden. –

Antwort

3

Sie sagen, dass Sie überprüfen, ob die Liste nicht empty() ohne Mutex gehalten wird. Aber empty() ist keine Thread-sichere Methode. Sie müssen es nicht aufrufen, während Sie (möglicherweise) gleichzeitig die Liste in einem anderen Thread ändern.

Gibt es einen Code, der Elemente aus der Liste entfernt? Es ist möglich, dass, wenn die Liste nicht leer ist, sie leer wird, bevor die Liste verarbeitet wird.

+0

Der einzige Thread, der Elemente aus der Liste entfernt, ist der Thread, der die Elemente der Liste wiederholt. Ok ich bekomme das leer ist kein Threadsicher, aber warum soll es in diesem Fall ein Problem sein? Diese Überprüfung vor dem Aufruf, den Mutex zu sperren, dient dazu, den Code zu optimieren, damit der Mutex gesperrt wird, wenn es wirklich nötig ist. Daten können verpasst werden, aber es wird später behandelt und es ist nicht Teil dieses Problems (ich glaube schon). Vielen Dank! –

+0

Sie zeigen nicht wirklich genug von Ihrem Code, um bessere Vermutungen zu machen. Vielleicht ist die Liste, die du 'empty()' nennst, und die Liste, die du überprüfst, verschiedene Listen. Versuchen Sie, die Adresse und die Anzahl der Elemente in der Liste zu drucken, sobald Sie sie leer finden, und noch einmal, bevor Sie darüber iterieren. Und technisch gesehen ruft das Aufrufen von 'empty()' bei gleichzeitigem Zugriff auf die Liste undefiniertes Verhalten auf und es kann _anyything_ passieren. – davmac