简体   繁体   中英

How to run a function on a separate thread, if a thread is available

How can I run a function on a separate thread if a thread is available, assuming that i always want k threads running at the same time at any point?

Here's a pseudo-code

For i = 1 to N
   IF numberOfRunningThreads < k
      // run foo() on another thread 
   ELSE
      // run foo()

In summary, once a thread is finished it notifies the other threads that there's a thread available that any of the other threads can use. I hope the description was clear.

My personal approach: Just do create the k threads and let them call foo repeatedly. You need some counter, protected against race conditions, that is decremented each time before foo is called by any thread. As soon as the desired number of calls has been performed, the threads will exit one after the other (incomplete/pseudo code):

unsigned int global_counter = n;

void fooRunner()
{
    for(;;)
    {
        {
            std::lock_guard g(global_counter_mutex);
            if(global_counter == 0)
                break;
            --global_counter;
        }
        foo();
    }
}

void runThreads(unsigned int n, unsigned int k)
{
    global_counter = n;
    std::vector<std::thread> threads(std::min(n, k - 1));
    // k - 1: current thread can be reused, too...
    // (provided it has no other tasks to perform)
    for(auto& t : threads)
    {
        t = std::thread(&fooRunner);
    }
    fooRunner();
    for(auto& t : threads)
    {
        t.join();
    }
}

If you have data to pass to foo function, instead of a counter you could use e. ga FIFO or LIFO queue, whatever appears most appropriate for the given use case. Threads then exit as soon as the buffer gets empty; you'd have to prevent the buffer running empty prematurely, though, eg by prefilling all the data to be processed before starting the threads.

A variant might be a combination of both: exiting, if the global counter gets 0, waiting for the queue to receive new data eg via a condition variable otherwise, and the main thread continuously filling the queue while the threads are already running...

you can use ( std::thread in <thread> ) and locks to do what you want, but it seems to me that your code could be simply become parallel using openmp like this.

#pragma omp parallel num_threads(k)

#pragma omp for
for (unsigned i = 0; i < N; ++i)
{
auto t_id = omp_get_thread_num();
if (t_id < K)
   foo()
else
   other_foo()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM