进程和线程
进程是程序执行时的一个实例,即它是程序已经执行到何种程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成(拥有很多相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其他的线程共享进程所拥有的全部资源。
“进程——资源分配的最小单位,线程——程序执行的最小单位”
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
每个线程都有一个自己唯一的ID,类型是pthread_t ,实际上就是int型
线程通过pthread_create()函数创建,这个函数的声明为
int pthread_create( pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
其中第一个参数为我们的进程ID,
第二个参数为线程的属性,默认为NULL,也就是非分离属性,非分离属性下一个进程结束之后,
它所占用的系统资源并没有完全真正的释放,也没有真正终止。
第三个参数为服务函数,我们把需要线程去做的事情写进函数内就可以完成,
第四个参数为服务函数的参数,可以指定一个结构体这样就可以让服务函数使用多种属性的变量
主线程执行结束之后并不会等子线程运行就结束了,所以通常我们有几种做法
1.让主线程运行完sleep几秒钟,等待子线程运行。
2.让主线程调用退出函数pthread_exit();主线程退出不影响子线程运行
线程回收函数 int pthread_jion(pthread_t thread, voidretval);**
当我们的子线程结束之后可以将数据返回给主线程,相当于主函数调用子函数,我们可以在子函数中调用pthread_exit(void* val)
其中val为返回给主线程的数据,在主线程中需要调用pthread_jion(pthread_t thread, void**retval)来接收数据,
pthread_jion的第一个参数为接收进程的ID号,第一个进程为接收数据变量的地址,可以定义一个变量来接收
这里贴出代码方便理解
#include<stdio.h>
#include<pthread.h>
int a;
void my_fun(void *arg)
{
int i=0;
for(;i<3;i++)
{
printf("child pthread %d\n",i);
}
printf("child id is %d\n",pthread_self());
a=1000;
pthread_exit(&a);//线程退出,返回a的地址
}
int main(void)
{
pthread_t tid;
int i=0;
pthread_create(&tid,NULL,my_fun,NULL);
for(;i<3;i++)
{
printf("parent pthread %d\n",i);
}
void *val=NULL;
pthread_join(tid,&val);//回收线程退出后的数据
int *p=(int *)val;
printf("\nval = %d\n",*p);
return 0;
}
其实还可以在create线程时候使用第四个参数传给服务函数,这样也可以达到同样效果
但是这里有一个小小的问题,当主线程调用pthread_jion()函数的时候,主线程是处于阻塞状态的,
主线程不能做其他的事情,所以我们要加以改进,调用pthread_detach(pthread_t pthread);函数,
用主线程和对应的子线程分离,这样当主线程退出的时候也不会释放子线程的资源了