确保线程池中的所有线程都在等待任务

时间:2019-05-07 14:24:15

标签: c linux multithreading pthreads threadpool

这是我第一次尝试多线程,并且我正在尝试在c中创建线程池,作为分配的一部分。因此,只允许我使用系统调用和pthread,但是我遇到的问题不需要在分配中解决-这只是我要学习的,但我仍然只想使用这些资源。 /> 我为我的线程池创建了一个结构,并在每个创建的线程上运行了一个函数-等待任务进入队列。 我想确保所有线程在完成线程池创建功能之前都在等待特定的wait_condition-(即:正在等待空队列状态)。 如果我不能确保所有线程都在等待任务进入队列,则以下代码片段将创建一个池并在将任何任务出队之前销毁它,因为在线程到达cond_wait之前将stop变量设置为true:

void test()
{
   int i;
   ThreadPool* tp = tpCreate(5);
   for(i=0; i<5; ++i)
   {
      tpInsertTask(tp,foo(),args);
   }
   //NO_WAIT flag is raised so the pool wont finish
   //remaining tasks in queue before stopping
   tpDestroy(tp,NO_WAIT);
}

这些是我创建的结构:

typedef struct thread_pool
{
    int             poolSize;
    volatile int    stop ;
    volatile int    running;
    OSQueue*        queue ;
    pthread_t*      threadID;
    pthread_mutex_t shared_lock;
    pthread_cond_t  emptyQ ;
    pthread_cond_t  poolStarted;
}ThreadPool;

//this is used to run Tasks in queue
struct TaskHandler

Bellow是线程池的简化创建函数: (safe_lock只是一个锁定池中唯一互斥量并检查mutex_lock(&m)返回值的函数。)

ThreadPool* tpCreate(int numOfThreads) {
    ThreadPool *tp = (ThreadPool *) malloc(sizeof(ThreadPool));

    /** ... **/

    //create pool
    for (i = 0; i < numOfThreads; i++) {
        err = pthread_create(&tp->threadID[i], NULL, start, tp);
        /** error check ..**/
    }
    //wait for the last function to reach waiting status
    safe_lock(tp);
    do{
        //wait until the last thread has reached waiting status
        pthread_cond_wait(&tp->poolStarted,&tp->shared_lock);
        //set thread-pool status as running
        tp->running = TRUE;
    }while(!tp->running);
    safe_unlock(tp);

    return tp;
}

以下代码显示了我已经尝试过的内容, 这是在池中创建的每个线程上运行的启动函数:

void* start(void* args) {
    ThreadPool *tp = (ThreadPool *) args;
    if (!tp) {
        return NULL;
    }
    //i did allso try to replace condition to while(!stop)
    while (TRUE) {
        TaskHandler *taskHandler = NULL;
        safe_lock(tp);
        if (shouldStop(tp)) {
            safe_unlock(tp);
            return NULL;
        } else if (osIsQueueEmpty(tp->queue)) {
            //if current thread is the last to be created , signal to create function
            if (!tp->running &&
                    tp->threadID[tp->poolSize - 1] == pthread_self() ) {
                pthread_cond_signal(&tp->poolStarted);
            }else{
                //signals when a task pushed to queue
                int err = pthread_cond_wait(&tp->emptyQ, &tp->shared_lock);
                /** error check .. **/
            }
        }
        taskHandler = (TaskHandler *) osDequeue(tp->queue);
        safe_unlock(tp);
        /** if task!=null run it **/
    }
}

停止功能:

void stopThreads(ThreadPool* tp){
    //sanity check
    if(!tp ){
        return;
    }
    safe_lock(tp);
    tp->stop = TRUE;
    pthread_cond_broadcast(&tp->emptyQ);
    safe_unlock(tp);
}

我的逻辑说,在创建最后一个线程时,它将一直向主线程发送信号,直到将运行条件设置为true为止; 因此它停止发信号,可以安静地等待任务入队。
我还试图计算达到cond_wait的线程数,但没有成功,因为据我所知,cond_wait并不容纳信号队列,因此我无法统计有多少线程确实达到了该条件,有时还没有信号当主线程未再次达到cond_wait时发送。
因此,这是我经过多次尝试才能获得的最好成绩,但是该池在停止之前仍运行可变数量的功能。 当然,我想避免使用睡眠或while循环进行任何繁忙的等待。
我将不胜感激任何帮助, 谢谢。

0 个答案:

没有答案