> 文章列表 > day10 线程池及gdb调试多线程

day10 线程池及gdb调试多线程

day10 线程池及gdb调试多线程

目录

线程池的概念

概念:

必要性:

线程池的基本结构

线程池的实现

 完整代码

线程的GDB调试


线程池的概念

概念:

通俗的讲就是一个线程的池子,可以循环的完成任务的一组线程集合;

必要性:

我们平时创建一个线程,完成某一个任务,等待线程的退出。但当需要创建大量的线程时;

假设T1为创建线程时间,T2为在线程任务执行时间,T3为线程销毁时间;

当T1 + T3 > T2,这时候就不划算了,使用线程池可以降低频繁创建和销毁线程所带来的的凯西欧啊,任务处理时间比较短的时候这个好处非常显著。

线程池的基本结构:

1、任务队列,存储需要处理的任务,由工作线程来处理这些任务;

2、线程池工作线程,他是任务队列任务的消费者,等待新任务的信号;

线程池的实现

1、创建线程池的基本结构:

typedef struct Task;         //任务队列链表
typedef struct ThreadPool;   //线程池结构体

2、线程池的初始化:

pool_init() {创建一个线程池结构;实现任务队列互斥锁和条件变量的初始化;创建n个工作线程;
}

 使用互斥锁是因为,任务队列链表是一个临界资源;

3、线程池添加任务:

pool_add_task {判断是否有空闲的工作线程;给任务队列添加一个节点;给工作线程发送信号newtask
}

4、实现工作线程:

workThread {while(1) {等待newtask任务信号;从任务队列中删除节点;执行任务;}
}

5、线程池的销毁:

pool_destory {删除任务队列链表的所有节点,释放空间;删除所有的互斥锁条件变量;删除线程池,释放空间;
}

 完整代码

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>#define POOL_NUM 10//任务队列链表结构体;
typedef struct Task{void *(*func)(void *arg);void *arg;struct Task *next;
}Task;//线程池结构体;
typedef struct ThreadPool {pthread_mutex_t taskLock;pthread_cond_t newTask;pthread_t tid[POOL_NUM];Task *queue_head;int busywork;
}ThreadPool;//线程池变量;
ThreadPool *pool;//实现工作线程;
void *workThread(void *arg) {while (1) {pthread_mutex_lock(&pool->taskLock);pthread_cond_wait(&pool->newTask, &pool->taskLock);Task *ptask = pool->queue_head;pool->queue_head = pool->queue_head->next;pthread_mutex_unlock(&pool->taskLock);ptask->func(ptask->arg);pool->busywork--;}
}//被执行的工作内容
void *realwork(void *arg) {printf("finish work %d\\n", (int)arg);
}//线程池添加任务;
void pool_add_task(int arg) {//判断Task *newTask;pthread_mutex_lock(&pool->taskLock);while(pool->busywork >= POOL_NUM) {pthread_mutex_unlock(&pool->taskLock);usleep(10000);pthread_mutex_lock(&pool->taskLock);}pthread_mutex_unlock(&pool->taskLock);//创建一个新任务newTask = malloc(sizeof(Task));newTask->func = realwork;newTask->arg = arg;//将新任务添加到任务队列;pthread_mutex_lock(&pool->taskLock);Task *member = pool->queue_head;if (member == NULL) {pool->queue_head = newTask;}else{while(member->next != NULL) {member = member->next;}member->next = newTask;}pool->busywork++;pthread_cond_signal(&pool->newTask);pthread_mutex_unlock(&pool->taskLock);
}//线程池初始化;
void pool_init(){pool = malloc(sizeof(ThreadPool));pthread_mutex_init(&pool->taskLock, NULL);pthread_cond_init(&pool->newTask, NULL);pool->queue_head = NULL;pool->busywork = 0;//创建n个工作线程int i;for(i = 0; i < POOL_NUM; i++){pthread_create(&pool->tid[i], NULL, workThread, NULL);}
}//线程的销毁
void pool_destroy() {Task *head;while(pool->queue_head != NULL) {head = pool->queue_head;pool->queue_head = pool->queue_head->next;free(head);}pthread_mutex_destroy(&pool->taskLock);pthread_mutex__destroy(&pool->newTask);free(pool);
}int main() {pool_init();sleep(1);for (int i = 1; i < 20; i++) {pool_add_task(i);}sleep(5);pool_destory();}

运行结果:

编译错误:

error: ‘ThreadPool {aka struct ThreadPool}’ has no member named ‘head’

意义:ThreadPool 结构体没有head这个成员。

解决:检查是否拼写错误。

error: too few arguments to function ‘pthread_mutex_init’

意思:pthread_mutex_init这个函数参数少了

解决:检查函数的参数,添加对应的参数

线程的GDB调试

 显示线程:

info thread

切换线程:

thread id

GDB为特定线程设置断点:

break location thread id

GDB设置线程锁:

set scheduler-locking on/off

on:其他线程会暂停,可以单独调试一个线程