In modern C++ (vanaf C++11) bestaat er een rijke toolkit voor het werken met multi-threading: std::thread, mutexen en verschillende wrapper-objecten voor controle over toegang tot resources. Veilige interactie tussen threads vereist begrip van de volgende componenten:
Om racecondities te voorkomen, gebruik altijd RAII-wrappers waar mogelijk. Houd er rekening mee dat een poging om dezelfde mutex opnieuw vast te leggen zal leiden tot een deadlock (tenzij het een recursieve mutex is).
Voorbeeld van correcte werking:
#include <iostream> #include <mutex> #include <thread> std::mutex mtx; void printThreadSafe(int id) { std::lock_guard<std::mutex> lock(mtx); std::cout << "Thread " << id << std::endl; } int main() { std::thread t1(printThreadSafe, 1); std::thread t2(printThreadSafe, 2); t1.join(); t2.join(); }
Kan std::lock_guardstd::mutex worden gebruikt voor het implementeren van conditionele synchronisatie met std::condition_variable?
Antwoord: Nee! Voor het werken met std::condition_variable is beslist std::unique_lockstd::mutex nodig, omdat lock_guard geen methoden biedt voor controle over de locking (bijvoorbeeld tijdelijk loslaten — unlock — en vervolgens opnieuw vastleggen), die nodig zijn bij het wachten op een notificatie.
Voorbeeld:
std::mutex mtx; std::condition_variable cv; bool ready = false; void waitForEvent() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{return ready;}); // Verdere verwerking }
Verhaal
In het project werd handmatig gewerkt met mtx.lock()/mtx.unlock(). Bij het gooien van een uitzondering tussen lock/unlock bleef de mutex vergrendeld — meerdere threads "hingen". Na de vervanging door RAII (
std::lock_guard) verdween het probleem.
Verhaal
Bij het notificeren via std::condition_variable werd std::lock_guard gebruikt in plaats van std::unique_lock. Als gevolg daarvan compileerde het programma niet op nieuwe compilators, en op de oude was er een runtime assertie door een inconsistent API.
Verhaal
In de code werd unlock() op std::lock_guard aangeroepen voor "handmatige" controle over toegang tot de mutex. Dit leidde tot onbepaalde gedragingen op verschillende compilators, soms tot een crash van de applicatie. Het werd duidelijk dat lock_guard geen handmatige vrijgave ondersteunt, een migratie naar unique_lock was nodig.