Mutexes are used to protect shared data structures from being concurrently accessed. If a mutex is destroyed while a thread is blocked waiting for that mutex, critical sections and shared data are no longer protected.
...
Unfortunately, this code contains a race condition, allowing the mutex to be destroyed before it is unlocked, because start_threads()
may invoke the lock's destructor before all of the threads have finished using the lock. This behavior This behavior is undefined.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <mutex> #include <thread> const size_t max_threads = 10; void do_work(size_t i, std::mutex *pm) { std::lock_guard<std::mutex> guard(*pm); // Access data protected by the lock. } void start_threads(void) { std::thread threads[max_threads]; std::mutex m; for (size_t i = 0; i < max_threads; ++i) { threads[i] = std::thread(do_work, i, &m); } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <mutex> #include <thread> const size_t max_threads = 10; void do_work(size_t i, std::mutex *pm) { std::lock_guard<std::mutex> guard(*pm); // Access data protected by the lock. } std::mutex m; void start_threads(void) { std::thread threads[max_threads]; for (size_t i = 0; i < max_threads; ++i) { threads[i] = std::thread(do_work, i, &m); } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <mutex> #include <thread> const size_t max_threads = 10; void do_work(size_t i, std::mutex *pm) { std::lock_guard<std::mutex> guard(*pm); // Access data protected by the lock. } void run_threads(void) { std::thread threads[max_threads]; std::mutex m; for (size_t i = 0; i < max_threads; ++i) { threads[i] = std::thread(do_work, i, &m); } for (size_t i = 0; i < max_threads; ++i) { threads[i].join(); } } |
...