C语言 线程池,当没有更多的任务需要完成时,如何正确地终止所有线程?

ffx8fchx  于 2023-03-28  发布在  其他
关注(0)|答案(1)|浏览(203)

到目前为止,我设置了一个全局变量taskCompleted来跟踪已经完成了多少任务;executeTask()在达到一定数量时终止。但是程序似乎在完成所有提交的任务后仍然挂起。这是为什么?

#define THREAD_NUM 4

typedef struct Task {
    int a, b;
} Task;

Task taskQueue[256];
int taskCount = 0;
int taskCompeleted = 0;

pthread_mutex_t mutex;
pthread_cond_t taskAvailable;

void executeTask(Task* task) {
    //usleep(50000);
    int result = task->a + task->b;
    printf("The sum of %d and %d is %d\n", task->a, task->b, result);
}

void submitTask(Task task) {
    pthread_mutex_lock(&mutex);
    taskQueue[taskCount] = task;
    taskCount++;
    pthread_cond_signal(&taskAvailable);
    pthread_mutex_unlock(&mutex);
}

void* startThread(void* args) {
    while (1) {
        Task task;

        pthread_mutex_lock(&mutex);
        while (taskCount == 0) {
            if (taskCompleted >= 10) {
                pthread_mutex_unlock(&mutex); 
                return 0;
            }
            pthread_cond_wait(&taskAvailable, &mutex);
        }

        task = taskQueue[0];
        int i;
        for (i = 0; i < taskCount - 1; i++) {
            taskQueue[i] = taskQueue[i + 1];
        }
        taskCount--;
        taskCompeleted++;
        pthread_mutex_unlock(&mutex);
        executeTask(&task);
    }
}

int main(int argc, char* argv[]) {
    pthread_t th[THREAD_NUM];
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&taskAvailable, NULL);
    int i;
    for (i = 0; i < THREAD_NUM; i++) {
        if (pthread_create(&th[i], NULL, &startThread, NULL) != 0) {
            perror("Failed to create the thread");
        }
    }

    for (i = 0; i < 10; i++) {
        Task t = {
            .a = i,
            .b = i
        };
        submitTask(t);
    }

    for (int i = 0; i < THREAD_NUM; i++) {
        if (pthread_join(th[i], NULL) != 0) {
            perror("Failed to join the thread");
        }
    }
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&taskAvailable);

    return 0;
}
8e2ybdfx

8e2ybdfx1#

我建议添加一个变量,线程可以在检查新任务是否可用的同时进行检查:

#include <stdbool.h>

int taskCount = 0;
int taskCompleted = 0;
bool shutdown = false;  // added

void shutdown_queue() {
    pthread_mutex_lock(&mutex);
    shutdown = true;
    pthread_cond_broadcast(&taskAvailable); // tell all threads to wake up
    pthread_mutex_unlock(&mutex);
}

thread函数中的循环将变成(快速退出,即使还有任务剩余):

void* startThread(void* args) {
    while (true) {
        Task task;

        pthread_mutex_lock(&mutex);
        while(!shutdown && taskCount == 0) {           // check for not shutdown
            pthread_cond_wait(&taskAvailable, &mutex);
        }
        if(shutdown) {                                 // if shutdown, bail out
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
        // ...
    }
}

或者,仅在任务队列耗尽时退出:

void* startThread(void* args) {
    while (true) {
        Task task;

        pthread_mutex_lock(&mutex);
        while(taskCount == 0) {           // check for not shutdown
            if(shutdown) {                // if shutdown, bail out
                pthread_mutex_unlock(&mutex);
                return NULL;
            }
            pthread_cond_wait(&taskAvailable, &mutex);
        }
        // ...
    }
}

然后可以调用shutdown_queue来通知所有线程终止。

相关问题