结束线程
1.让线程的入口函数结束执行------最常见最主要使用的结束方式
2.pthread_exit:让本线程结束------但是很少使用它,它的参数是 void* 表示线程结束的返回结果(很少用到);如果exit 全部线程都没了,这个不能混淆了。exit 结束进程。
void* ThreadEntry(void* arg) { //新线程入口,参数 (void)arg; while (1) { printf("In ThreadEntry, %lu\n", pthread_self()); //pthread_self() 获取自己的线程的ID Sleep(1); } pthread_exit(NULL); }
3.pthread_cancel:让任意一个线程结束。(前提:本进程中的线程)
pthread_cancel(tid); //tid:对应线程的ID,结束该ID对应的线程
事务:要求具有“原子性”,要么不做,要么做完,不能做一半,半途而废,可能会导致数据被破坏。这样的后果非常严重。
等待线程:
目的和进程等待类似,防止出现类似僵尸进程的内存泄露情况。有回收资源的功能。
函数:
pthread_join(pthread_t thread,void **retval) 最重要的功能是等待。
参数:
pthread_t thread:等待指定ID<thread>线程
void **retval:输出型参数,可以无视他。NULL 就好了
pthread_join(tid, NULL); //等待线程ID为<tid> 的线程,结束之后在执行
新线程就一直执行,主线程就一直阻塞在新线程上。要查看阻塞到哪:pstask tid (这个非常非常重要,tid:进程ID)
线程分离(类似 忽略SIGCHLD 信号,即不需要知道结果)
线程分离之后,就不需要pthread_join来回收了。
函数:
pthread_detach(pthread_t thread)
参数:
pthread_t thread:线程ID
pthread_detach(tid); while (1) { printf("In Main Thread", pthread_self()); //pthread_self() 获取自己的线程的ID } //分离之后,主线程就继续无限循环打印,哪个新线程就分离了。
一个多线程的小场景:
例如,计算一个很大的矩阵相乘,可以使用多线程的方式来计算,每个线程计算其中的一部分结果,最终等所有的线程都执行完毕,有主线程来汇总最终的结果,主线程就需要pthread_join 来保证所有的线程都算完了,主线程才继续执行。
例子:多线程利用多核资源
void* ThreadEntry(void* arg) { //新线程入口,参数
(void)arg;
while (1);
return NULL;
}
int main() {
pthread_t tid1,tid2;
pthread_create(&tid1, NULL, ThreadEntry, &arg);
pthread_create(&tid2, NULL, ThreadEntry, &arg);
……
//主线程
while (1)
return 0;
}
结果:用top命令 看 CPU占有率,这时候会是百分之二百,线程数量的增多,CPU占有率就会上升,最多提高到你的内核数量线程部署越多越好,到达一定程度,上限之后,线程数继续增多,反而会降低效率,线程多了,CPU调度就越多,
问:那多少线程又合适呢?
不能回答到底有多少数字,要看执行的是什么任务:CPU密集/IO密集,其中IO操作是不占CPU的。
线程的数目喝工作的类型有关,究竟多少合适,要通过测试来判定。
例子:线程之间能够共享虚拟地址
//线程控制相关函数
//创建进程
//参数:
//pthread_t *thread:线程ID的地址
//const pthread_attr_t *att:是个结构体,设置属性,一般用不到,NULL就好了
//void *(*strart_routine)(void*):函数指针,就相当于新线程的入口函数,指定了新线程执行那个代码
//void *arg:上个函数指针,入口函数的参数就是这个。
//创建线程
#include <stdio.h>
#include<pthread.h> //头文件
#include <unistd.h> //sleep头文件
int g_count = 0; //栈上的变量
void* ThreadEntry(void* arg) { //新线程入口,参数
(void)arg;
while (1) {
printf("In ThreadEntry\n");
++g_count;
Sleep(1);
}
return NULL;
}
int main() {
//new,malloc就在堆上创建
pthread_t tid;
pthread_create(&tid, NULL, ThreadEntry, &arg);
//主线程
pthread_detach(tid); //线程分离
while (1)
{
printf("In Main Thread %d\n", g_count);
}
return 0;
}
//结果在不断+1 可见供用一个虚拟地址空间
//Makefile文件中
teat:teat.c
gcc $^ -o $@ - lpthread
结果就会不断 +1,就可以看出来:共用一个虚拟地址空间