一、线程
1.1 线程的概念
线程是轻量级的进程。
进程是分配资源的最小单位,线程是调度的最小单位。
线程不会单独分配内存空间,线程共用进程的资源。
线程之间通信比较方便,但是不安全。
多线程没有多进程安全。
多线程效率比较高。线程创建比较快,公用进程的资源。线程上下文的切换比较迅速,因为线程占用的内存资源少。
多进程比较浪费资源,多线程节省资源。
每一个进程中,最少有一个线程,叫做主线程。
线程使用的是第三方库,需要添加#include<pthread.h>头文件,在编译的时候,需要添加 -lpthread参数
安装线程man手册:sudo apt-get install manpages*
1.2 线程创建
1.2.1 pthread_create(线程创建的函数)
#include <pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);
功能:创建线程
参数:thread:线程号attr:线程属性 -- 传NULL即可start_routine:线程体 - 在线程体中定义了线程要执行的任务arg:给线程传参
返回值:成功返回0,失败返回错误码
1.2.2 线程创建函数的使用示例1(不关注返回值)
#include <my_head.h>
pthread_t tid;void *thread_func(void *arg){while (1){printf("线程1\n");sleep(1);}}
int main(int argc,const char *argv[]){int ret = 0;ret = pthread_create(&tid,NULL,thread_func,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}while (1){printf("我是主线程\n");sleep(1);}return 0;
}
运行结果:
1.2.3 线程创建函数的使用示例2 (传递参数)
#include <my_head.h>
pthread_t tid1,tid2;
typedef struct Struct{char name[32];char sex;short tall;
}stu_t;void *thread_func(void *arg){while(1){printf("线程id = %d\n",*(int *)arg);sleep(1);}
}
void *thread_func2(void *arg){while (1){printf("%s %c %hd",((stu_t *)(arg))->name,((stu_t *)(arg))->sex,((stu_t *)(arg))->tall);sleep(1);}
}
int main(int argc,const char *argv[]){int ret = 0;stu_t stu1 = {.name = "xiaoming",.sex = 'm',.tall = 180,};stu_t stu2 = {.name = "hong",.sex = 'w',.tall = 170,};ret = pthread_create(&tid1,NULL,thread_func2,(void *)&stu1);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}while (1){printf("主线程\n");sleep(1);}return 0;
}
运行实例:
1.3 线程的执行顺序问题
没有顺序,时间片轮询,上下文切换
1.4 线程的内存空间问题
#include<my_head.h>
pthread_t tid1,tid2;int var1 = 100;void *thread_func(void *arg){while(1){printf("var1 = %d\n",var1);//5s之后,输出数值变成200,下面的线程对全局变量数值做了修改sleep(1);}
}void *thread_func2(void *arg){sleep(5);var1 = 200;
}int main(int argc,const char *argv[]){int ret = 0;ret = pthread_create(&tid1,NULL,thread_func,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}while(1){// printf("我是主线程....\n");sleep(1);}return 0;
}
1.5 pthread_self(获取线程号)
#include <pthread.h>
pthread_t pthread_self(void);
功能:获取线程的线程号
参数:空
返回值:获取到的线程号,这个函数总是调用成功
pthrread_self使用示例
#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){printf("我的线程号%ld\n",pthread_self());
}
int main(int argc,const char *argv[]){int ret = 0;ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}while(1){sleep(1);}return 0;
}
运行结果:
2.7 pthread_join(线程资源回收)
#include <pthread.h> -- 所需头文件
int pthread_join(pthread_t thread,void **retval);
功能:阻塞回收指定的线程资源
参数:thread:要回收的现成的线程idretval:线程退出的状态
返回值:成功返回0,失败返回错误码
pthread_join函数的使用(不传参)
#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){printf("我是子线程,我要结束了\n");pthread_exit(NULL);//传参NULL,不反悔退出状态
}
int main(int argc,const char *argv[]){int ret = 0;while(1){ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}pthread_join(tid2,NULL);sleep(1);}return 0;
}
运行结果:
pthread_join 函数的使用(不传参)
#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){printf("子进程,我要结束了\n");pthread_exit(NULL);//传NULL,不返回退出状态
}
int main(int argc,const char *argv[]){int ret = 0;while(1){ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(ret != 0){printf("创建线程失败:%s\n",strerror(ret));return -1;}pthread_join(tid2,NULL);//不传参NULLsleep(1);}return 0;
}
运行结果:
pthread_join 函数的使用(传参)
#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){int *retval = (int *)malloc(sizeof(int));*retval = 100;printf("我是子线程,我要结束了\n");pthread_exit((void *)retval);//传NULL,不反悔退出状态//不可传局部变量的地址,会导致数据错误或者程序崩溃
}
int main(int argc,const char *argv[]){int ret = 0;int *retval;ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(ret != 0){printf("创建线程失败%s\n",strerror(ret));return -1;}pthread_join(tid2,(void **)&retval);printf("retval = %d\n",*retval);free(retval);sleep(1);return 0;
}
运行结果:
1.8 pthread_detach(线程分离)
线程的状态分为两种 分离态 和 结合态。
结合态的线程,需要其他线程调用pthread_join为线程回收资源。
分离态的线程,操作系统会自动为线程回收资源。
线程默认的状态:结合态。
#include <pthread.h> -- 所需头文件
int pthread_detach(pthread_t thread);
功能:将线程设置为分离态
参数:thread:线程id
返回值:成功返回0,失败返回错误码
#include <my_head.h>
pthread_t tid1,tid2;void *thread_func2(void *arg){pthread_detach(pthread_self());//将线程设为分离态,线程结束之后,才做系统自动为其分配资源printf("我是子线程,我要结束了\n");pthread_exit(NULL);//传NULL,不反悔退出状态
}int main(int argc,const char *argv[]){int ret = 0;while(1){ret = pthread_create(&tid2,NULL,thread_func2,NULL);if(0 != ret){printf("创建线程失败:%s\n",strerror(ret));return -1;}sleep(1);}
}
运行结果: