Ich habe eine Reihe von Daten, die gleichzeitig verarbeitet werden müssen mit Multi-Threading, die Anzahl der Daten ist angeblich größer als die Anzahl der Threads. Ich entschied mich dafür, die Daten in eine Art von Warteschlange zu stellen, so dass jeder freie Thread seinen Teil platzen und verarbeiten kann, bis die Warteschlange leer ist. Ich könnte eine einfache STL-Warteschlange verwenden und sie durch einen Mutex sperren, wenn ich ein Element daraus entfernen möchte, aber ich möchte einen Lock-Free-Ansatz versuchen. Zur gleichen Zeit ist mein Projekt zu klein, um von einer Drittanbieter-Bibliothek abhängig zu sein, die blockfreie Strukturen bietet, tatsächlich brauche ich nur eine atomare Auslagerung. Also habe ich beschlossen, meine eigene Warteschlange zu implementieren, basierend auf einem Vektor mit einem Zeiger auf den „Kopf“ und erhöhen diesen Zeiger atomar:Der einfachste Weg, atomar zu entketten?
template <typename T>
class AtomicDequeueable
{
public:
// Assumption: data vector never changes
AtomicDequeueable(const std::vector<T>& data) :
m_data(data),
m_pointer(ATOMIC_VAR_INIT(0))
{}
const T * const atomicDequeue()
{
if (std::atomic_load(&m_pointer) < m_data.size())
{
return &m_data
[
std::atomic_fetch_add(&m_pointer, std::size_t(1))
];
}
return nullptr;
}
private:
AtomicDequeueable(const AtomicDequeueable<T>&) {}
std::atomic_size_t m_pointer;
const std::vector<T>& m_data;
};
Themen Funktion sieht wie folgt aus:
void f(AtomicDequeueable<Data>& queue)
{
while (auto dataPtr = queue.atomicDequeue())
{
const Data& data = *dataPtr;
// processing data...
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
Meine Erfahrung mit Lock-Free-Strukturen und Primitive ist wirklich arm, also frage ich mich: Wird mein Ansatz richtig funktionieren? Sicherlich habe ich es auf Ideone getestet, aber ich weiß nicht, wie es sich mit echten Daten verhalten wird.
Lock-frei und einfach? Oh Junge. Sie haben ein Datenrennen in Ihrem Code. Stellen Sie sich vor, dass Ihre Warteschlange der Größe 'n' auf' n-1' gefüllt ist, jetzt zwei Threads gleichzeitig erfolgreich sind in 'std :: atomic_load (& m_pointer)
user2296177
Ihre Funktion "atomicDequeue" sieht nicht atomar aus. Denken Sie darüber nach, was passiert, wenn 2 Threads die if-Anweisung durchlaufen, wenn 'm_pointer'' m_data.size() - 1' ist. – Kevin