一.基本概念介绍
进程
运行中的程序,程序运行的动态描述
线程
- 线程是轻量级进程,没有独立的地址空间,共享进程的资源
- 在linux下线程是CPU的基本调度单位。在宏观上线程是并行的,使用多线程可以有效提高cpu的使用率。
- 一个程序中有一个主线程,可以创建其他线程并行执行
- 一个程序有多个线程就有多个执行流程。相当于单进线程是一条路走下去,而多线程是有很多条路同时走。
为啥有了进程还需要线程
- 线程是轻量级的进程,系统维护线程需要的资源比进程少
- 线程的切换比进程切换更快
- 线程之间的通信更为简单,直接共享全局变量
线程同步
1.互斥锁
多个线程共享一个资源时,会出现意想不到的结果。使用互斥锁来解决线程之间的资源竞争问题。
一个线程访问资源必须先获取锁,访问完资源再解锁。如果没有获取到锁就挂起线程(线程挂起不消耗CPU)
2. 条件变量
条件变量是对互斥锁的补充,它解决线程之间相互合作的问题。使用条件变量都搭配一个互斥锁来使用:
加锁
while(条件)
{
等待条件变量(挂起线程 释放锁)
}
解锁
加锁
操作
解锁
发送变量线程量量线程量的线程
二.线程池原理
1.什么线程池
线程池:负责创建和销毁线程,让程序员使用线程变得简单。
2.什么时候使用线程
当需要创建大量的线程处理任务,并且任务执行的时间很短。这种情况下创建线程和销毁线程的时间大于任务执行的时间程序效率低,在这种情况下可以使用线程池。
3.线程池的实现原理
线程池内部维护着一个任务队列。初始化时创建一堆线程执行,线程的入口函数实现从任务队列中取出任务执行。任务执行完不用销毁线程等待下一个任务来继续执行。如果任务队列中没有任务就挂起线程,当向线程池添加任务时唤醒一个线程执行。
4.线程池结构体设计
_互斥锁 操作任务和线程内部数据时必须是线程安全的
-条件变量 使用条件变量来实现工作线程的挂起和唤醒
-任务队列头指针 保存任务
-线程id数组指针 保存线程id 方便控制线程
-线程运行状态标识 启动和停止线程
-线程销毁标识 用来销毁线程池
-最大线程数
-任务队列个数
5.任务队列设计
-任务队列使用链表实现
6.对外提供接口
-线程初始化
-添加任务
-线程池的销毁
三.线程池的实现
#include <stdio.h>
#include <stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<string.h>
/*================================================
* 宏定义
* ===============================================*/
#define THREAD_DESTORY 0
#define SUCCESS 0
#define FAILURE 1
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
/*================================================
* 结构体定义
* ===============================================*/
/*回调接口*/
typedef void *(*THREAD_FUNC)(void*);
/*任务接口结构体*/
typedef struct task
{
THREAD_FUNC func; /*线程回调函数*/
void *arg; /*回调函数参数*/
struct task *next;
}task;
/*线程池结构体定义*/
typedef struct threadpool
{
pthread_cond_t task_queue_ready; /*任务队列条件变量*/
pthread_mutex_t tpool_lock; /*线程池互斥锁*/
task * tasks; /*任务链表头*/
pthread_t * t_ids; /*线程id数组指针*/
int isdestory; /*线程池销毁标志*/
int max_size; /*线程最大个数*/
int tasks_size; /*任务队列等待个数*/
}threadpool;
/*================================================
* 全局变量定义
* ===============================================*/
threadpool *g_pool=NULL; /*线程池指针*/
int g_isrunning=0; /*线程池运行状态 销毁线程时用到*/
/*================================================
* 函数定义
* ===============================================*/
int tpool_init(int thread_count); /*线程池初始化函数*/
void t_pool_destory(); /*线程池销毁函数*/
void routine(); /*线程入口函数*/
int add_task(THREAD_FUNC func,void* arg); /*线程池添加任务函数*/
/*================================================
* 函数实现
* ===============================================*/
/*
* 函数名:tpool_init
* 函数功能:初始化线程池
* 参数
* thread_count 线程池线程的个数
* 返回值
* FAILURE 失败
* SUCCESS 成功
* */
int tpool_init(int thread_count)
{
if(NULL != g_pool)
{
LOG("已经初始化过啦 \n");
return FAILURE;
}
LOG("开始初始化\n");
g_pool = (threadpool*)malloc(sizeof(struct threadpool));
LOG("%d\n",sizeof(struct threadpool));
if(NULL == g_pool)
{
LOG("内存分配失败\n");
return FAILURE;
}
memset(g_pool,'\0',sizeof(sizeof(struct threadpool)));
g_isrunning=1;
pthread_cond_init(&g_pool->task_queue_ready,NULL);
pthread_mutex_init(&g_pool->tpool_lock,NULL);
g_pool->isdestory=1;
g_pool->max_size=thread_count;
g_pool->tasks_size=0;
g_pool->tasks=NULL;
g_pool->t_ids = (pthread_t*)malloc(sizeof(pthread_t)*g_pool->max_size);
if(NULL == g_pool->t_ids)
{
LOG("分配内存失败\n");
free(g_pool);
return FAILURE;
}
int i=0,ret;
for(;i<g_pool->max_size;i++)
{
ret = pthread_create(&g_pool->t_ids[i],NULL,(void*(*)(void*))routine,NULL);
LOG("%d\n",g_pool->t_ids[i]);
if(ret)
{
g_pool->t_ids[i]=0;
t_pool_destory();
}
}
return SUCCESS;
}
/*
* 函数名:tpool_destory
* 函数功能:线程池销毁
* 参数
*
* 返回值
*
* */
void t_pool_destory()
{
LOG("t_pool_destory\n");
if(NULL == g_pool)
{
return ;
}
pthread_mutex_lock(&g_pool->tpool_lock);
if(THREAD_DESTORY == g_pool->isdestory)
{
LOG("t_pool_destory isdestory is 0\n");
pthread_mutex_unlock(&g_pool->tpool_lock);
return;
}
g_isrunning=0;
g_pool->isdestory=THREAD_DESTORY;
pthread_cond_broadcast(&g_pool->task_queue_ready);
pthread_mutex_unlock(&g_pool->tpool_lock);
free(g_pool->t_ids);
task* t = NULL;
while(NULL != g_pool->tasks)
{
t= g_pool->tasks;
g_pool->tasks=g_pool->tasks->next;
free(t);
}
/*释放锁和条件变量*/
pthread_mutex_destroy(&g_pool->tpool_lock);
pthread_cond_destroy(&g_pool->task_queue_ready);
/*释放线程池*/
free(g_pool);
g_pool=NULL;
}
/*
* 函数名:routine
* 函数功能:从任务列表中取出任务执行
* 参数
*
* 返回值
*
* */
void routine()
{
task* t=NULL;
LOG("routine \n");
if(NULL==g_pool)
{
LOG("routine g_pool is null \n");
pthread_exit(NULL);
}
while(g_isrunning)
{
LOG("routine while中\n");
pthread_mutex_lock(&g_pool->tpool_lock);
/*任务队列为空 线程池不销毁线程睡眠*/
while((0>=g_pool->tasks_size)&&(1==g_pool->isdestory))
{
LOG("routine 任务队列为空 线程挂起\n");
pthread_cond_wait(&g_pool->task_queue_ready,&g_pool->tpool_lock);
}
/*线程池销毁就退出线程*/
if(THREAD_DESTORY==g_pool->isdestory)
{
LOG("isdestory broadcast wake thread exit\n");
pthread_mutex_unlock(&g_pool->tpool_lock);
pthread_exit(NULL);
}
t=g_pool->tasks;
g_pool->tasks = g_pool->tasks->next;
g_pool->tasks_size--;
pthread_mutex_unlock(&g_pool->tpool_lock);
t->func(t->arg);
free(t);
}
LOG("routine g_isrunning is 0 thread exit\n");
pthread_exit(NULL);
}
/*
* 函数名:add_task
* 函数功能:给线程池提交任务
* 参数
* func 任务回调函数
* arg 回调函数参数
* 返回值
* 0 成功
* 其他 错误
* */
int add_task(THREAD_FUNC func,void* arg)
{
/*参数检查*/
if(NULL== g_pool)
{
LOG("add_task g_pool is null\n");
return 1;
}
if(NULL==func)
{
LOG("add_task func is null\n");
return 1;
}
pthread_mutex_lock(&g_pool->tpool_lock);
/*创建一个任务节点*/
task * t = (task*)malloc(sizeof(task));
if(NULL==t)
{
LOG("add_task malloc is failure\n");
pthread_mutex_unlock(&g_pool->tpool_lock);
return 1;
}
t->arg=arg;
t->func=func;
t->next=NULL;
task* w= g_pool->tasks;
if(NULL!=w)
{
while(NULL!=w->next)
{
w=w->next;
}
w->next=t;
}
else
{
g_pool->tasks=t;
}
g_pool->tasks_size++;
LOG("create task is success\n");
pthread_cond_signal(&g_pool->task_queue_ready);
pthread_mutex_unlock(&g_pool->tpool_lock);
}