进程:分配资源(内存)的最小单位,有独立的 进程地址空间,有独立的pcb。
线程:程序执行的最小单位,没有独立的进程地址空间,有独立的pcb。每一个进程由一个或 者多个线程组成,即每个进程至少有一个主线程。
独享:栈空间(内核栈、用户栈)
共享 ./text ./data ./rodata ./bsss heap 全局变量
与进程相似,每个线程都有自己的id,获取线程id函数如下:
pthread_t pthread_self(void);
在头文件
返回值:本线程id,其类型为pthread_t
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_rountn)(void *), void *arg);
pthread_t *tid:传出参数,新创建的线程 id
const pthread_attr_t *attr:线程属性。可以设置,默认为NULL。
void *(*start_rountn)(void *):子线程回调函数。线程创建成功,该函数会被自动调用。
void *arg:回调函数的参数。没有的话,传NULL。
返回值:成功:0 ,失败:errno。
#include
#include
#include
#include
#include
void *thread_fun(void *argc){ //回调函数,子线程执行的函数
printf("new tread\n");
return NULL;
}
int main(int argc,char*argv[]){
int ret;
pthread_t tid;
ret = pthread_create(&tid,NULL,thread_fun,NULL); //创建子线程
if(ret ! = 0){
printf("create failed\n");
exit(1);
}
sleep(1); //等待子线程运行完
printf("mian thread\n");
return 0;
}
#include
#include
#include
#include
#include
void *thread_fun(void *argc){
int th = (int)argc;
sleep(th); //子线程依次执行
printf("--I am thread %dth, pid=%d, tid=%lu\n",th+1,getpid(),pthread_self()); //打印进程id,线程id
return NULL;
}
int main(int argc,char*argv[]){
int i;
int ret;
pthread_t tid;
for(i = 0; i < 5;i++){ //循环创建线程
ret = pthread_create(&tid,NULL,thread_fun,(void*)i);
if(ret != 0){
printf("create failed\n");
exit(1);
}
}
sleep(i); //等待所有子线程执行完
printf("main: I am main , pid=%d,tid=%lu\n",getpid(),pthread_self()); //打印进程id,主线程id
return 0;
}
主线程生成并执行子线程,主线程可能将于子线程之前结束,但是如果主线程需要用到子线程的处理结果,即主线程需要等待子线程执行完成之后再结束,这个时候就要用到pthread_join()方法了。
pthread_join()有两种作用:
1.用于等待其他线程结束:当调用 pthread_join() 时,当前线程会处于阻塞状态,直到被调用的线程结束后,当前线程才会重新开始执行。
2.对线程的资源进行回收:如果没有对线程使 pthread_join() 的话,该线程结束后并不会释放其内存空间,这会导致该线程变成了“僵尸线程”。分离属性线程除外。
int pthread_join(pthread_t thread, void **retval);
thread: 待回收的线程id
retval:传出参数。 回收的那个线程的退出值。
返回值:成功:0,失败:errno
void *thread_fun(void *argc){ //回调函数,子线程执行的函数
sleep(5);
printf("new thread sleep 5s\n");
return NULL;
}
int main(int argc,char*argv[]){
int ret;
pthread_t tid;
ret = pthread_create(&tid,NULL,thread_fun,NULL); //创建子线程
if(ret != 0) {
printf("create failed\n");
}
pthread_join(tid,NULL); //主线程阻塞
printf("main thread\n");
return 0;
}
运行结果:
当主线程运行到pthread_join(tid,NULL),便会阻塞在这里,等待子线程回调函数执行完,然后主线程继续下执行。
typedef struct {
int id;
int age;;
char name[64];
}stu;
void *thread_fun(void *arg)
{
stu * retvar = (stu *)malloc(sizeof(exit_t));
retvar->id=1;
retvar-> age= 16;
strcpy(retvar->name,"uzi");
//子线程退出
return (void *)retvar;
}
int main(void)
{
pthread_t tid;
int ret;
stu * retval;
ret = pthread_create(&tid,NULL,thrd_func,NULL);
if(ret != 0){
printf("create failed\n");
exit(1);
}
pthread_join(tid,(void **)&retval); //接受回调函数的返回值
printf("子线程返回值为\n");
printf("id = %d ,age = %d,name = %s\n",retval->id,retval->age,retval->name);
return 0;
}
int val = 0;
void *thread_fun(void *arg){
int i;
i = (int)arg;
sleep(i);
switch(i){
case 0 :
val = 100;
return (void*)val;
// break;
case 1 :
val = 200;
return (void*)val;
// break;
case 2 :
val = 300;
return (void*)val;
// break;
case 3 :
val = 400;
return (void*)val;
// break;
default :
val = 500;
return (void*)val;
// break;
}
return NULL;
}
int main(void)
{
pthread_t tid[5]; //保存线程id
int ret;
int i;
int * retval[5]; //存储接受的返回值
for(i = 0;i < 5;i++){
ret = pthread_create(&tid[i],NULL,thread_fun,(void*)i); //给线程传参i
if(ret != 0){
printf("create failed\n");
exit(1);
}
}
for(i = 0;i < 5 ;i++){
pthread_join(tid[i],(void **)&retval[i]); //接受回调函数的返回值i
printf("I am thread %dth,val=%d,tip=%lu\n",i+1,val,pthread_self());
}
printf("I am main val=%d,tip=%lu\n",val,pthread_self());
return 0;
}
参考https://blog.csdn.net/liuyuchen282828/article/details/100345308
调用函数的线程将挂起等待,直到 id 为 thread 的线程终止。 thread 线程以不同的方法终止,通过 pthread_join 得到的终止状态是不同的,总结如下:
1.如果 thread 线程通过 return 返回,retval 所指向的单元里存放的是 thread 线程函数的返回值,此时进程会返回到调用者,不会结束。
2.如果 thread 线程被别的线程调用 pthread_cancel 异常终止掉, retval 所指向的单元里存放的是常数PTHREAD_CANCELED。
3.如果 thread 线程是自己调用 pthread_exit 终止的,retval 所指向的单元存放的是传给 pthread_exit 的参数。
4.如果对 thread 线程的终止状态不感兴趣,可以传 NULL 给 retval 参数。
线程区别于进程,线程可以将自己与主线程分离开。可以用函数形式分离,也可以通过在创建线程时,将其属性设置为分离属性。
函数的形式很简单
int pthread_detach(pthread_t thread);
thread: 待分离的线程id
返回值:成功:0,失败:errno
主线程来获取子线程的返回值
void *thread_fun(void *arg){
int n=3;
while(n--){
printf("thread count %d\n",n);
sleep(1);
}
return (void *)1;
}
int main(void){
pthread_t tid;
void *tret;
int err;
pthread_create(&tid,NULL,thread_fun,NULL);
pthread_detach(tid); //线程分离
while(1){
err = pthread_join(tid,&tret); //获取返回值
printf("---------err= %d\n",err);
if(err != 0)
fprintf(stderr,"thread error: %s\n",strerror(err));
else
fprintf(stderr,"thread exit code %d\n",(int)tret);
sleep(1);
}