目录
- 线程控制
- 1 线程创建
- 2 线程等待
- 3 线程终止
- 4 线程分离
- pthread_t id && LWP
线程控制
1 线程创建
功能:创建一个新的线程
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)
(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *thread_run(void *args){
while(1){
//printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
sleep(1);
}
}
int main(){
pthread_t tid[5];
int i;
for(i = 0; i < 5; i++){
pthread_create(tid+i, NULL, thread_run, (void *)"new thread");
}
while(1){
printf("我是主线程,我的thread ID:%lu\n", pthread_self());
printf("##############################begin#########################\n");
for(i = 0; i < 5; i++){
printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
}
printf("###############################end##########################\n");
sleep(1);
}
}
2 线程等待
一般而言,线程也是需要等待的,如果不等待,可能会导致类似于“僵尸进程”的问题!
用下面这个函数实现等待
举个例子:
下面这个程序会因为单个线程的野指针问题而造成所有线程崩溃
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *thread_run(void *args){
int num = *(int*)args;
while(1){
//printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
sleep(1);
//野指针问题,测试一个线程崩整个进程则崩的问题
if(num == 3){
printf("thread number: %d quit\n", num);
int *p = NULL;
*p = 1000;
}
}
}
#define NUM 5
int main(){
pthread_t tid[NUM];
int i;
for(i = 0; i < NUM; i++){
pthread_create(tid+i, NULL, thread_run, (void *)&i);
sleep(1);
}
while(1){
printf("我是主线程,我的thread ID:%lu\n", pthread_self());
printf("##############################begin#########################\n");
for(i = 0; i < NUM; i++){
printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
}
printf("###############################end##########################\n");
sleep(1);
}
return 0;
}
运行结果
- 使用
pthread_join
进行线程等待
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *thread_run(void *args){
int num = *(int*)args;
while(1){
printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
sleep(1);
break;
//野指针问题,测试一个线程崩整个进程则崩的问题
//if(num == 3){
// printf("thread number: %d quit\n", num);
// int *p = NULL;
// *p = 1000;
//}
}
//退出异常,不需要处理
//这里的返回值也可以是其他变量,不一定为int型,但不能是临时的
return (void*)111;
}
#define NUM 1
int main(){
pthread_t tid[NUM];
int i;
for(i = 0; i < NUM; i++){
pthread_create(tid+i, NULL, thread_run, (void *)&i);
sleep(1);
}
//void* 32.4 64.8, 指针变量。本身就可以充当某种容器保存数据
void *status = NULL;
//退出信息
pthread_join(tid[0], &status);
printf("ret: %d\n", (int)status);
//while(1){
// printf("我是主线程,我的thread ID:%lu\n", pthread_self());
// printf("##############################begin#########################\n");
// for(i = 0; i < NUM; i++){
// printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
// }
// printf("###############################end##########################\n");
// sleep(1);
//}
return 0;
}
线程出异常,pthread_join不需要处理,这是进程的问题
3 线程终止
-
函数中return
-
pthread_exit
新线程通过
pthread_exit
终止自己(vsexit
是终止进程,只想终止一个线程时不要调用) -
pthread_cancel
直接发起一个请求给目标进程,即取消目标线程
#include <stdio.h> #include <pthread.h> #include <unistd.h> void *thread_run(void *args){ int num = *(int*)args; while(1){ printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self()); sleep(2); //break; //野指针问题,测试一个线程崩整个进程则崩的问题 //if(num == 3){ // printf("thread number: %d quit\n", num); // int *p = NULL; // *p = 1000; //} } //线程出异常不需要处理 //这里的返回值可以是其他变量,并非只能int,但不能是临时变量 //pthread_exit((void*)123); //return (void*)111; } #define NUM 1 int main(){ pthread_t tid[NUM]; int i; for(i = 0; i < NUM; i++){ pthread_create(tid+i, NULL, thread_run, (void *)&i); sleep(1); } printf("wait sub thread...\n"); sleep(5); printf("cancel sub thread....\n"); pthread_cancel(tid[0]); //void* 32.4 64.8, 指针变量。本身就可以充当某种容器保存数据 void *status = NULL; pthread_join(tid[0], &status); printf("ret: %d\n", (int)status); sleep(3); //while(1){ // printf("我是主线程,我的thread ID:%lu\n", pthread_self()); // printf("##############################begin#########################\n"); // for(i = 0; i < NUM; i++){ // printf("我创建的线程[%d]是:%lu\n", i, tid[i]); // } // printf("###############################end##########################\n"); // sleep(1); //} return 0; }
运行结果,可以发现,取消线程,退出码为-1
可以用其他线程取消主线程,但此时可能会造成僵尸进程问题,此时里面还可能有子线程在运行。
4 线程分离
分离之后的线程不需要被join,运行完毕之后,会自动释放Z,pcb。
一般都是自己分离自己,也可以主线程分离新线程。
一个线程被设置分离之后,就不能再被join了。
pthread_t id && LWP
我们查看到的线程id是pthread库的线程id,不是Linux内核中的LWP,pthread库的线程id是一个内存地址!