boost::mutex richtig reservieren
-
Hallo, ich habe ein Problem mit threads und mutex von boost.
Ich habe ein Thread in dem eine while-Schleife läuft. Außerdem nutze ich einen Mutex um zu gewährleisten, dass alles ausgeführt wird.
[obj1]
while(...){
mutex.lock;// etwas code
mutex.unlock;
}Dann habe ein weiteres Objekt, dem ich den selben Mutex übergeben habe.
Dort rufe ich eine Funktion auf und lock den Mutex.[obj2]
void beispiel::func1()
{
mutex.lock;// etwas code
mutex.unlock;
}Mein Problem ist jetzt, dass es extrem lange dauert, bis der Code aus func1 ausgeführt wird, weil der Mutex nicht frei wird. Ich dachte, wenn jemand einen Mutex in beschlag nimmt, dann wird er automatisch informiert wenn ihn jemand freigibt.
Aber offensichtlich wird in der while-Schleife nach dem unlock sofort wieder zum lock gesprungen und func1 darf weiterhin warten....
Kann mir jemand sagen was ich falsch mache bzw. wie ich mein Problem lösen kann?
-
Die "Warteschlage" bzgl Mutex-Locking ist in der Regel aus Performanz-Gründen nicht "fair". Wenn ein Thread den Mutex freigibt und sofort danach wieder in Besitz nehmen will, ist die Chance groß, dass kein anderer Thread dazwischen funkt. Die anderen Threads werden wahrscheinlich schon benachrichtig, kommen aber zu spät zum Zug.
Für einen Lösungsvorschlag muss man besser über das Bescheid wissen, was Du eigentlich machen willst. Es sieht für mich auf den ersten Blick so aus, als ob Dein Ansatz grundlegend falsch ist.
-
Ich vermute auch dass du irgendwas beim Design deines Programmes falsch angepackt hast, und sich ein anderes, vermutlich eleganteres Design finden liesse, welches das Problem einfach umgeht.
Ansonsten kannst du dir aus einer Mutex + einer Condition-Variable relativ einfach eine eigene Mutex mit FIFO Scheduling bauen.
Grob skizziert:
class FifoMutex { public: void Lock() { ThreadID const myId = CurrentThreadID(); ScopedLock lock(m_mutex); // als letzter in die warteliste eintragen m_waiters.push_back(myId); // warten bis wir ganz vorne sind while (m_waiters.front() != myId) m_cv.wait(lock); } void Unlock() { ThreadID const myId = CurrentThreadID(); ScopedLock lock(m_mutex); assert(m_waiters.front() == myId); // das müssen immer noch wir sein, sonst muss iwo was schief gelaufen sein m_waiters.pop_front(); // wir sind fertig -> austragen m_cv.signal_all(); // andere informieren dass sich was getan hat } private: Mutex m_mutex; ConditionVariable m_cv; std::deque<ThreadID> m_waiters; };
-
Vielen Dank für die Hilfe.
Das Fifo Beispiel konnte mein Problem lösen.
Für einen Lösungsvorschlag muss man besser über das Bescheid wissen, was Du eigentlich machen willst. Es sieht für mich auf den ersten Blick so aus, als ob Dein Ansatz grundlegend falsch ist.
Ich habe eine Physic-Engine implementiert.
Die Physikberechnung läuft in einer while-Schleife mit 60FPS in einem eigenen Thread.Die physikalischen Objekte möchte ich selber bewegen können.
Allerdings darf ich nicht ein Objekt bewegen, wenn zum aktuellen Zeitpunkt ein Physik-Schritt berechnet wird. Deswegen locke ich einen Mutex.Wie gesagt läuft das jetzt wie erwünscht, aber ich bin auch für andere Lösungsansätze offen.
