C 销毁线程池中线程的问题

C 销毁线程池中线程的问题,c,linux,pthreads,threadpool,C,Linux,Pthreads,Threadpool,我在Linux环境中使用C编程语言实现了一个线程池。有一个阻塞任务队列,我们可以将任务放入任务队列中,线程池中的线程从任务队列中获取任务,如果任务队列为空,它将阻塞等待一个条件信号,表示任务队列不为空。 线程池中的线程运行的函数是: static void *do_worker(void *arg) { printf("new thread %d\n", pthread_self()); ThreadPool *pool = (ThreadPool

我在Linux环境中使用C编程语言实现了一个线程池。有一个阻塞任务队列,我们可以将任务放入任务队列中,线程池中的线程从任务队列中获取任务,如果任务队列为空,它将阻塞等待一个条件信号,表示任务队列不为空。 线程池中的线程运行的函数是:

    static void *do_worker(void *arg)
    {
        printf("new thread %d\n", pthread_self());
        ThreadPool *pool = (ThreadPool *)arg;
        while (1) {
           printf("thread %d try to get new task\n", pthread_self());
           Task task;
           //printf("before get_task\n");
           task = get_task(&pool->task_queue);
           printf("thread %d get_task\n", pthread_self());
           if (task.ftn == NULL ) {
               break;
           }
           task.ftn(task.arg);
           //printf("finish new task\n");
           //printf("I'm thread %d\n", pthread_self());
        }
        printf("thread %d exit\n", pthread_self());
        pthread_exit(NULL);
    }
当我将普通任务添加到队列中时,这看起来不错,但当我尝试使用毒药任务销毁线程池时,就像这样:

    void destroy_threadpool(ThreadPool *pool)
    {
     int i;
     /* put poison to let the threads exit */
     for (i = 0; i < pool->t_cnt; i++) {
         Task null_task;
         null_task.ftn = NULL;
         null_task.arg = NULL;
         printf("insert poison task\n");
         insert_task(pool, null_task);
     }

     for (i = 0; i < pool->t_cnt; i++) {
         pthread_join(pool->tids[i], NULL);
     }
    }
ThreadPool和TaskQueue的定义如下:

    typedef struct {
        void *(*ftn)(void *arg);
        void *arg;
    } Task;

    typedef struct {
        Task tasks[MAXTASK];
        int front;
        int back;
        pthread_mutex_t mutex;
        pthread_cond_t no_empty;
        pthread_cond_t no_full;
    } TaskQueue;

    typedef struct {
        pthread_t tids[MAXTHREAD];
        int t_cnt;
        TaskQueue task_queue;
    } ThreadPool;

您使用什么语言/技术?添加相应的标签以帮助专家找到您的问题。您还可以发布
get\u task
的代码吗?
insert\u task
实际上做什么?insert\u task只是put\u task的包装。。所有这些printf调用通常都在那里吗,或者您添加它们是为了调试吗?还有一个提示—您应该只需要一片药丸—当线程得到它时,它可以在退出之前将它放回队列。这应该适用于所有线程,无论有多少线程。
    typedef struct {
        void *(*ftn)(void *arg);
        void *arg;
    } Task;

    typedef struct {
        Task tasks[MAXTASK];
        int front;
        int back;
        pthread_mutex_t mutex;
        pthread_cond_t no_empty;
        pthread_cond_t no_full;
    } TaskQueue;

    typedef struct {
        pthread_t tids[MAXTHREAD];
        int t_cnt;
        TaskQueue task_queue;
    } ThreadPool;