Erstellen einer Warteschlange Blockiert
Manchmal ist diese Umsetzung und Durchführung von BlockingQueue
funktioniert einfach. Manchmal ist es segfaults. Irgendeine Idee warum?
#include <thread>
using std::thread;
#include <mutex>
using std::mutex;
#include <iostream>
using std::cout;
using std::endl;
#include <queue>
using std::queue;
#include <string>
using std::string;
using std::to_string;
#include <functional>
using std::ref;
template <typename T>
class BlockingQueue {
private:
mutex mutex_;
queue<T> queue_;
public:
T pop() {
this->mutex_.lock();
T value = this->queue_.front();
this->queue_.pop();
this->mutex_.unlock();
return value;
}
void push(T value) {
this->mutex_.lock();
this->queue_.push(value);
this->mutex_.unlock();
}
bool empty() {
this->mutex_.lock();
bool check = this->queue_.empty();
this->mutex_.unlock();
return check;
}
};
void fillWorkQueue(BlockingQueue<string>& workQueue) {
int size = 40000;
for(int i = 0; i < size; i++)
workQueue.push(to_string(i));
}
void doWork(BlockingQueue<string>& workQueue) {
while(!workQueue.empty()) {
workQueue.pop();
}
}
void multiThreaded() {
BlockingQueue<string> workQueue;
fillWorkQueue(workQueue);
thread t1(doWork, ref(workQueue));
thread t2(doWork, ref(workQueue));
t1.join();
t2.join();
cout << "done\n";
}
int main() {
cout << endl;
//Multi Threaded
cout << "multiThreaded\n";
multiThreaded();
cout << endl;
}
- Wenn es segfaults, ich nehme an, du könntest die Zeile code wo ist es passiert? Könnte nur hilfreich sein, zu wissen...
- Was passiert, wenn Sie überprüfen, ob die
itemQueue
leer ist, dann lassen Sie andere thread einige Arbeit, und dannpop()
ein item??? - Diese Frage hat genug code, jeder kann es ausprobieren und selbst sehen, wo das problem ist. Gibt es nicht viel überflüssigen code, so dass es nicht weit Weg ein lehrbuch SSCCE und sicherlich zu vertreten hat.
- Ich habe eine harte Zeit zu glauben, dass "Wo ist der Fehler in diesem Programm?" jemals sein könnte ist eine gute Frage.
- Gerne erklären mein denken auf diese eine weitere auf meta oder im chat, wenn Sie möchten, aber lassen Sie uns das bitte vermeiden Sie Chats in den Kommentaren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Siehe hier:
Was bekomme ich von der Vorderseite () - leer-std-container?
Schlimme Dinge passieren, wenn Sie anrufen
.front()
auf einen leeren container, besser überprüfen.empty()
ersten.Versuchen:
Hinweis: Da Atomare Operationen sind wichtig, auf diese Art von Schlange, würde ich empfehlen, API-änderungen:
Besser noch, wenn man eigentlich mit, wo es darauf ankommt, werden Sie wahrscheinlich wollen, um Einträge zu markieren, im Einsatz vor dem löschen im Falle des Scheiterns.
std::
- und C++ selbst. Weit eher mit C++/CLI, C#, C, Java, eigentlich alles außer Vanille C++ und STL. Jede Sprache definieren Ausnahme, wie eine unsichere misfeature verdient eine miss in meinem Buch. Ich meine, wer implementiert eine leere Warteschlange Lesen als segfault?!std:lock_guard
Redewendungen zur Verfügung gestellt von der c++ - standard, oder Rollen Sie Sie, wenn nötig leicht!unique_lock<mutex> lock(this->mutex_)
Ergebnisse in lesbarer code..front()
funktioniert. Also entschied ich mich für highlight Fallstricke, die ich bin vertraut mit. Ich weiß wirklich nicht genug überlock_guard
zu kommentieren. Also werde ich nicht. Wirklich, mitstd::string
die einzige Ausnahme, die möglich ist, aus dem Speicher. Das sollte wohl tödlich sein in den meisten einfachen Programme sowieso.Sollte das problem lag hier:
Behalten Sie den mutex, wenn die überprüfung ein Wert übrig ist, lassen Sie dann den mutex und es kann passieren, dass ein anderer thread ausgeführt wird, findet heraus, dass ein Wert übrig ist, und es erscheint. Im schlimmsten Fall, dass kein Element übrig ist, und danach den ersten thread versucht zu pop während kein element mehr übrig ist.
Die Lösung ist die front - /pop-Anrufe auf der internen Warteschlange in der gleichen Abschnitt als die Kontrolle für die leere in der gleiche gesperrte Abschnitt, dann das Verhalten wäre immer definiert werden.
Ein weiterer Vorschlag wäre, die Nutzung
std::lock_guard
bei der Arbeit mit mutex, weil es verbessert die Lesbarkeit und stellt sicher, dass der mutex wird freigegeben, egal was passiert.In Anbetracht der Tatsache, diese zwei Ratschläge, Ihre
pop
Methode könnte wie folgt Aussehen:std::queue.front()
Verhalten ist die überraschung hier nicht, dass threads, die Vorrang vor jedem anderen. Wenn Sie hatten erwähnt es explizit, ich würde nicht die Mühe mit einer Antwort.pop
Methode, die er implementiert.std::lock_guard<std::mutex> lock(this->mutex_);
?