线程的创建
概念:Linux内核没有线程,线程是pthread库提供的,同一进程中的线程共享相同的地址空间
创建:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
成功返回0,失败时返回错误码
thread 线程对象
attr 线程属性,NULL代表默认属性
routine 线程执行的函数
arg 传递给routine的参数 ,参数是void * ,注意传递参数格式
coding:
//线程的创建
//需注意编译时必须在末尾加对外部库函数的调用命令 -lpthread
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(char* arg){
printf("This is fun\n");
return NULL;
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret;
ret=pthread_create(&tid,NULL,(void*)fun,NULL);
printf("This is main\n");
sleep(1); //主函数需要等待一下,否则线程容易创建失败!
return 0;
}
注:
1. 主进程的退出,它创建的线程也会退出
2. 创建需要时间,如果主进程马上退出,那线程不能得到执行
获取线程的ID&线程的退出
通过在线程里面调用pthread_self函数获取线程ID
void pthread_exit(void* retval); //线程的退出,可以达到清理线程的作用,建议使用它退出线程,不建议使用return 退出线程
coding:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(char* arg){
printf("This is fun,tid=%lu\n",pthread_self());//获取线程ID
pthread_exit(NULL);//线程的退出
printf("after exit\n");//由于线程已经退出,所以无法输出
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret;
ret=pthread_create(&tid,NULL,(void*)fun,NULL);
printf("This is main,tid=%lu\n",tid);//也可以获取线程ID
sleep(1);
return 0;
}
线程间参数的传递
coding:
1、完美且麻烦的方式
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(char* arg){
printf("This is fun,tid=%lu,pid=%d\n",pthread_self(),getpid());
printf("get arg=%d\n",*(int*)arg);//着重看格式转化
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret,arg=5;
ret=pthread_create(&tid,NULL,(void*)fun,(void* )&arg);//着重看传参方式
printf("This is main,tid=%lu\n",tid);
sleep(1);
return 0;
}
2、简单的方式:会有警告,但是可以运行,需要程序员保证长度不丢失
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(char* arg){
printf("This is fun,tid=%lu,pid=%d\n",pthread_self(),getpid());
printf("get arg=%d\n",(int)arg);//简单的转换
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid;
int ret,arg=5;
ret=pthread_create(&tid,NULL,(void*)fun,(void* )arg);//简单化的传参
printf("This is main,tid=%lu\n",tid);
sleep(1);
return 0;
}
多线程的创建
coding:
//创建五个线程
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(char* arg){
printf("This is fun,tid=%lu,pid=%d\n",pthread_self(),getpid());
printf("get arg=%d\n",*(int*)arg);
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid[5];
int ret,arg=5;
int i;
for(i=0;i<5;i++){
ret=pthread_create(&tid[i],NULL,(void*)fun,(void* )&i);
sleep(1);//放在最后的时候输出不美观
printf("This is main,tid=%lu\n",tid[i]);
}
return 0;
}
运行结果:
线程的回收(3种方式)
1、
int pthread_join(pthread_t thread, void **retval);
注:pthread_join 是阻塞函数,如果回收的线程没有结束,则主函数一直等待
coding:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* fun(void* arg){
printf("This is fun\n");
sleep(5);
pthread_exit("This is return");
}
int main(int argc, const char *argv[])
{
pthread_t tid;
void* ret;
pthread_create(&tid,NULL,fun,NULL);
pthread_join(tid,&ret);//线程回收函数
printf("ret=%s\n",(char*)ret);//输出返回的字符串
sleep(1);
return 0;
}
2、
最简便的方式
pthread_detach(pthread_self());//放在线程函数开始处即可,获取线程ID后,等待线程结束并该回收线程
3、
创建线程时设置为分离属性--主函数中进行
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);