I have several threads working on different problems at the same time.
Sometimes some threads are waiting for the results of other threads, whose status is set by a boolean variable.
When a thread has to wait for the result of another thread, I do it like this:
while(!finished)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
I'm looking for a better way to signal the scheduler to proceed to the next thread. Something like this:
while(!finished)
{
schedular.schedule();
}
What is the best way to signal to the scheduler that the current thread has nothing more to do and that it should continue with the next thread?
The approach you're currently using with std::this_thread::sleep_for
introduces unnecessary delays and CPU usage, even with a small sleep duration. A better way to handle this scenario is to use synchronization primitives provided by the C++ Standard Library, such as std::condition_variable
. These allow a thread to wait efficiently, yielding execution to the scheduler until it is notified.
std::condition_variable
Here’s how you can rewrite your code using std::condition_variable
:
#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <atomic>
std::atomic<bool> finished{false}; // Atomic variable for thread-safe status
std::mutex mtx; // Mutex to protect condition variable
std::condition_variable cv; // Condition variable for signaling
void worker_thread() {
// Simulate some work
std::this_thread::sleep_for(std::chrono::seconds(2));
// Notify that the work is finished
{
std::lock_guard<std::mutex> lock(mtx);
finished = true;
}
cv.notify_one(); // Notify waiting thread
}
void waiting_thread() {
// Wait for the result
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return finished.load(); }); // Wait until finished is true
std::cout << "Work is finished, proceeding..." << std::endl;
}
int main() {
std::thread t1(worker_thread);
std::thread t2(waiting_thread);
t1.join();
t2.join();
return 0;
}
Condition Variable (std::condition_variable
):
cv.wait
method efficiently puts the thread to sleep and releases the lock on the mutex while waiting.cv.notify_one
or cv.notify_all
is called, reducing CPU usage compared to a busy-wait loop.Atomic Variable (std::atomic<bool>
):
finished
flag is updated in a thread-safe manner without needing additional synchronization.Mutex (std::mutex
):
finished
) and is required for std::condition_variable
.This pattern is the recommended approach when dealing with threads that depend on each other's results. It minimizes CPU usage and leverages the operating system's efficient thread scheduling mechanisms.