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:其他线程会暂停,可以单独调试一个线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值