3.1线程概述
线程概述
线程和进程区别
线程和进程虚拟地址空间
进程是读时共享,写时复制。线程共享虚拟地址空间,只是.text段(代码段)有不一样。.text会分成一个个小段,线程1、线程2…分开存储在不同的段.text。各线程执行各自的代码。栈空间也会有不同,分成一个个小段分给各线程。
线程之间共享和非共享资源
NPTL
Linux系统线程库的发展概述
3.2 创建线程
线程操作
创建线程
出现报错及原因
线程是第三方库不是标准系统库,需要通过-l指定去指定库的名称
解决方案如下:
main函数中所有执行的代码为主线程的代码,子线程执行的代码为回调函数的代码
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
//函数指针,void*为万能指针
void * callback(void * arg) {
printf("child thread...\n");
printf("arg value: %d\n", *(int *)arg);
return NULL;
}
int main() {
pthread_t tid;
int num = 10;
// 创建一个子线程
int ret = pthread_create(&tid, NULL, callback, (void *)&num);
if(ret != 0) {
char * errstr = strerror(ret);
printf("error : %s\n", errstr);
}
for(int i = 0; i < 5; i++) {
printf("%d\n", i);
}
//预防子线程还在创建或子线程未抢占执行权,程序就退出,预防子线程的未被执行
sleep(1);
return 0; // exit(0);
}
显示结果:
3.3终止线程
#include <stdio.h>
#include <pthread.h>
#include <string.h>
void * callback(void * arg) {
printf("child thread id : %ld\n", pthread_self());
return NULL; // pthread_exit(NULL);终止子线程
}
int main() {
// 创建一个子线程
pthread_t tid;
int ret = pthread_create(&tid, NULL, callback, NULL);
if(ret != 0) {
char * errstr = strerror(ret);
printf("error : %s\n", errstr);
}
// 主线程
for(int i = 0; i < 5; i++) {
printf("%d\n", i);
}
printf("tid : %ld, main thread id : %ld\n", tid ,pthread_self());
// 让主线程退出,当主线程退出时,不会影响其他正常运行的线程(子线程)。
pthread_exit(NULL);
//该句没有被执行
printf("main thread exit\n");
//没有执行
return 0; // exit(0);
}
显示结果:
主线程和子线程是交替执行的,并发。
3.4连接已终止的线程
子进程一定是被父进程回收,子线程不一定需要被父线程回收,可以被任意线程回收,但一般是主线程回收子线程。如果子线程结束后不被回收,也会产生僵尸线程。
为何使用二级指针?
要想改变一级指针的值,函数调用传入参数为二级指针。
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
//全局变量,若为局部变量,栈空间数据,最后获取的是个随机的值
//线程退出时记得一定返回的是全局变量的值
int value = 10;
void * callback(void * arg) {
printf("child thread id : %ld\n", pthread_self());
// sleep(3);
// return NULL;
// int value = 10; // 局部变量
pthread_exit((void *)&value); // return (void *)&value;
}
int main() {
// 创建一个子线程
pthread_t tid;
int ret = pthread_create(&tid, NULL, callback, NULL);
if(ret != 0) {
char * errstr = strerror(ret);
printf("error : %s\n", errstr);
}
// 主线程
for(int i = 0; i < 5; i++) {
printf("%d\n", i);
}
printf("tid : %ld, main thread id : %ld\n", tid ,pthread_self());
// 主线程调用pthread_join()回收子线程的资源
int * thread_retval;//定义一个一级指针
//传递一级指针的地址作为二级指针,并转换为void **
ret = pthread_join(tid, (void **)&thread_retval);
if(ret != 0) {
char * errstr = strerror(ret);
printf("error : %s\n", errstr);
}
printf("exit data : %d\n", *thread_retval);
printf("回收子线程资源成功!\n");
// 让主线程退出,当主线程退出时,不会影响其他正常运行的线程。
pthread_exit(NULL);
return 0;
}
显示结果: