最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

multithreading - C++ give Schedular hint to schedul to the next thread for std::thread - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question asked Jan 20 at 9:50 ThomasThomas 2,2594 gold badges24 silver badges45 bronze badges 4
  • 4 Have a look at std::future/std::asynce, std::condition_variable, std::latch, std::barrier, which is best depends on your actual design/use case. Since you use sleep_for I think std::condition_variable::wait (+predicate) is most likely. Though std::async/std::future might work too – Pepijn Kramer Commented Jan 20 at 9:53
  • @PepijnKramer thanks a lot! std::condition_variable::wait seems to be the thing I was looking for =). I'll also take a look at the other sync possibilities, maybe I'll change my design. – Thomas Commented Jan 20 at 9:59
  • I thought it might be, just be careful always use a predicate in wait. Condition variables have this "spurious wakeup" thing where they can fall through even if the condition is not true (which the predicate will handle) – Pepijn Kramer Commented Jan 20 at 10:02
  • 1 Using a promise or a condition variable is good for isolated use-cases, but if the entire system is using them then I would really suggest you look into a task based scheduler instead of a thread-based one, overcomitting threads downgrades performance, ideally a system shouldn't have those signals, just tasks and dependencies. – Ahmed AEK Commented Jan 20 at 10:12
Add a comment  | 

1 Answer 1

Reset to default 2

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.

Using 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;
}

How It Works:

  1. Condition Variable (std::condition_variable):

    • The cv.wait method efficiently puts the thread to sleep and releases the lock on the mutex while waiting.
    • The thread is woken up only when cv.notify_one or cv.notify_all is called, reducing CPU usage compared to a busy-wait loop.
  2. Atomic Variable (std::atomic<bool>):

    • Ensures the finished flag is updated in a thread-safe manner without needing additional synchronization.
  3. Mutex (std::mutex):

    • Protects access to shared state (finished) and is required for std::condition_variable.

Advantages:

  • Efficiency: The thread doesn’t spin in a loop but is put to sleep until notified.
  • Scheduler-Friendly: It allows the thread to yield its execution completely until there’s meaningful work to do.
  • Scalable: Handles many threads without excessive CPU overhead.

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.

发布评论

评论列表(0)

  1. 暂无评论