目录
一、线程的概念
二,线程相关API
1,创建一个线程
2,线程的退出
3,线程资源的回收
4,线程间的同步机制
三,互斥
四,同步
五,线程池
一、线程的概念
1,线程是比进程更小的活动单位,它是进程中的一个执行路径(执行分支)。
2,线程同进程内其他线程共享进程的地址空间。
==> 线程的特点:
1) 创建一个线程比创建一个进程的开销要小的多(why?)
因为,在进程内部创建一个线程,不需要拷贝整个进程的地址空间。
2) 实现线程间通信十分方便,因为一个进程创建的多个线程直接共享整个进程的内存区域。
3) 线程也是一个动态的概念。
4) 进程是操作系统资源分配的最小单位,线程是调度的最小单位。
5) 在进程内创建多线程,可以提高系统的并行处理能力,加快进程的处理速度。
6) 每个进程会自动有一个主线程,就是main函数,这个主线程如果执行完了,那么
进程就结束了。
二,线程相关API
1,创建一个线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
注意: 在编译和链接时需要加 -pthread
2,线程的退出
有三种方式可以使线程结束:
(1) 线程函数返回
(2) 在线程函数中调用 pthread_exit()
void pthread_exit(void *retval);
@retval: 指针,用来返回返回值。等价于return 后面的值。
该值可以被 pthread_join()函数接收
(3) 被别的线程调用 pthread_cancel 把你给"取消"了
int pthread_cancel(pthread_t thread);
@thread: 指定要取消的线程ID
int pthread_setcancelstate(int state, int *oldstate);
@state : 要设置的取消状态属性
PTHREAD_CANCEL_ENABLE 可被别人取消
PTHREAD_CANCEL_DISABLE 不可被别人取消
@oldstate: 用来保存原来的取消状态属性
3,线程资源的回收
int pthread_join(pthread_t thread, void **retval);
@thread: 用来指定等待哪个线程退出
@retval: 是一个二级指针,指向的类型是void*,用来保存线程函数的返回值
pthread_join 用来等待一个指定的线程退出,该函数会阻塞调用进程,直到被等待的线程退出,
它有两个作用:
1) 阻塞值被等待线程退出,并接收它的返回值
2) 回收被等待线程的资源
4,线程间的同步机制
1) 互斥
多个线程同时访问一个共享资源时,我们应该要“避免竞争”
a. 信号量机制
SYSTEM V 信号量
POSIX 信号量(有名/无名)
b. 线程互斥锁(pthread mutex)
2) 同步
==> 条件变量
三,互斥
线程互斥锁(pthread mutex)专门用来实现在线程间互斥用的。
它的原理和功能、作用等都跟信号量一样。
pthread_mutex_init 创建一个互斥锁
pthread_mutex_destroy 销毁一个互斥锁
pthread_mutex_lock/trylock P操作
pthread_mutex_unlock V操作
四,同步
线程间的同步通过条件变量来实现
同步: 用来阻塞某个线程,直到另外一个线程达到某种条件之后再唤醒它。
==> 等
pthread_cond_init 初始化一个条件变量
pthread_cond_destroy 销毁一个条件变量
pthread_cond_wait/timewait 阻塞
pthread_cond_signal/broadcast 唤醒
#include#include #include int a=0; pthread_cond_t cond; pthread_mutex_t mutex; void* thread1(void* arg) { while(1) { printf("a:%dn",a++); sleep(1); if(a>10) { pthread_mutex_lock(&mutex);//P操作 printf("A: the condition is ok, i wake up you!n"); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex);//V操作 break; } } } void* thread2(void* arg) { if(a<=10) { printf("B: it's no condition, i sleep...n"); pthread_mutex_lock(&mutex);//P操作 pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex);//V操作 printf("B: thank you very much!n"); } } int main() { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex, NULL); pthread_t tid1,tid2; int r = pthread_create(&tid1,NULL,thread1,NULL); if(r) { perror("pthread_create failed"); return -1; } r = pthread_create(&tid2,NULL,thread2,NULL); if(r) { perror("pthread_create failed"); return -1; } pthread_join(tid1,NULL); pthread_join(tid2,NULL); }
五,线程池
pthread_pool.h
#ifndef __THREAD_POOL_H__ #define __THREAD_POOL_H__ #include#include #include #include #define MAX_TASK_NUM 10 #define SHUTDOWN_ON 0 #define SHUTDOWN_OFF 1 typedef struct node{ void *(*fun)(void *);//任务函数指针 void *arg; //任务参数 struct node *next; }Node_thr; typedef struct{ Node_thr *first; Node_thr *last; int NodeNum; //结点数量 int thr_Num; //活动线程数量 int shutdown; //是否关闭线程池标志位,当shutdown为1表示不再有任务添加进线程池 pthread_t *tid; //保存活动线程ID的地址的首地址 pthread_mutex_t mutex;//与条件变量绑定的互斥锁 pthread_cond_t cond;//实现同步操作的条件变量 pthread_mutex_t mutex_head;//保存链表头节点的互斥锁 }Head_thr; //线程池头结点 extern Head_thr *thread_pool_init(int thr_Num); //初始化一个线程池 extern int finish_thread_pool(Head_thr *thread_pool); //关闭一个线程池(等待任务结束,再销毁) extern int thread_pool_destroy(Head_thr *thread_pool); //销毁一个线程池 extern int add_task(Head_thr *thread_pool,void *(*fun)(void *),void *arg); //增加任务到线程池 extern int start_thread_pool(Head_thr *thread_pool); //创建所有的活动线程 extern void *active_thread(void *arg); //活动线程对应的线程函数 #endif
pthread_pool.c
#include "thread_pool.h"
//初始化一个线程池
Head_thr *thread_pool_init(int thr_Num)
{
Head_thr *pool = malloc(sizeof(*pool));
pool->first = NULL;
pool->last = NULL;
pool->NodeNum = 0;
pool->shutdown = SHUTDOWN_OFF;
pool->thr_Num = thr_Num;
pool->tid = malloc(sizeof(pthread_t)*thr_Num);
pthread_mutex_init(&(pool->mutex),NULL);
pthread_mutex_init(&(pool->mutex_head),NULL);
pthread_cond_init(&(pool->cond),NULL);
return pool;
}
//活动线程函数
void *active_thread(void *arg)
{
Head_thr *thread_pool = arg;
while(1)
{
pthread_mutex_lock(&(thread_pool->mutex_head));//P操作
if(thread_pool->shutdown==SHUTDOWN_ON && thread_pool->NodeNum==0)//等待
{
pthread_mutex_unlock(&(thread_pool->mutex_head));//V操作
pthread_mutex_lock(&(thread_pool->mutex));//P操作
pthread_cond_wait(&(thread_pool->cond),&(thread_pool->mutex));//唤醒有两个地方==》1.新增任务 2.关机
pthread_mutex_unlock(&(thread_pool->mutex));//V操作
pthread_mutex_lock(&(thread_pool->mutex_head));//P操作
}
if(thread_pool->shutdown==SHUTDOWN_OFF && thread_pool->NodeNum==0)//退出线程
{
pthread_mutex_unlock(&(thread_pool->mutex_head));//V操作, 禁止带锁死亡
pthread_exit(NULL);
}
Node_thr *p = thread_pool->first;
thread_pool->first = thread_pool->first->next;
thread_pool->NodeNum--;
pthread_mutex_unlock(&(thread_pool->mutex_head));//V操作
p->fun(p->arg);//执行任务
free(p);
}
}
//创建所有的活动线程
int start_thread_pool(Head_thr *thread_pool)
{
int r;
thread_pool->shutdown = SHUTDOWN_ON;
for(int i=0;ithr_Num;i++)
{
r = pthread_create(thread_pool->tid+i,NULL,active_thread,thread_pool);
if(r != 0)
{
perror("pthread_create failed");
return r;
}
}
return 0;
}
//关闭一个线程池(等待任务结束,再销毁)
int finish_thread_pool(Head_thr *thread_pool)
{
thread_pool->shutdown = SHUTDOWN_OFF;
pthread_mutex_lock(&(thread_pool->mutex));//P操作
pthread_cond_broadcast(&(thread_pool->cond));//唤醒所有的线程
pthread_mutex_unlock(&(thread_pool->mutex));//V操作
for(int i=0;ithr_Num;i++)//等活动线程结束
{
pthread_join(thread_pool->tid[i], NULL);//线程结束的条件为:
//1,线程池没有任务了 2,自身的任务做完了
}
return 0;
}
//销毁一个线程池
int thread_pool_destroy(Head_thr *thread_pool)
{
free(thread_pool->tid);
free(thread_pool);
return 0;
}
//增加任务到线程池
int add_task(Head_thr *thread_pool,void *(*fun)(void *),void *arg)
{
Node_thr *pnew = malloc(sizeof(*pnew));
pnew->fun = fun;
pnew->arg = arg;
pnew->next = NULL;
while(thread_pool->NodeNum >= MAX_TASK_NUM);//队列结点达到最大值,等一下
pthread_mutex_lock(&(thread_pool->mutex_head));//P操作
if(thread_pool->first == NULL)
{
thread_pool->first = pnew;
thread_pool->last = pnew;
}
else
{
thread_pool->last->next = pnew;
thread_pool->last = pnew;
}
thread_pool->NodeNum++;
pthread_mutex_unlock(&(thread_pool->mutex_head));//V操作
pthread_mutex_lock(&(thread_pool->mutex));//P操作
pthread_cond_signal(&(thread_pool->cond));
pthread_mutex_unlock(&(thread_pool->mutex));//V操作
return 0;
}



