1.线程相关的概念:
程序:二进制程序放置在存储媒介中(硬盘,光盘,软盘等)以物理文件形式存在。
进程:程序被触发后,执行者的权限与属性,程序的程序代码与所需数据等都会被加载到内存中,操作系统并给与这个内存内的单元一个标识符(PID),可以说,进程就是一个正在运行中的程序。
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
进程和线程的关系:线程是属于进程的,线程运行在进程的空间内,同一进程所产生的线程共享同一物理内存空间,当进程退出时改进程所产生的线程会被强制退出并清除,一个进程至少需要一个线程作为它的指令执行体。 进程管理着资源(cpu,内存,文件等)而线程分配到某个cpu 上去执行。
多线程:线程相关的执行状态和存储变量放在线程控制表内。一个进程可以有多个线程,有多个线程控制表及堆栈寄存器,共享一个用户地址空间。
cpu会分配给每一个线程只有极少的运行时间,时间一到就交出运行权,所有线程被快速的切换执行,因为cpu的执行速度非常的快,所以在执行的过程中我们可以简单的认为这些线程是“并发”执行的。
2.线程编程:
线程标识
线程ID
•进程ID在整个系统中是唯一的
•线程ID只在它所属的进程环境中有效
函数: pthread_self()
pthread_t 用于声明线程ID
创建线程:
•调用该线程函数的入口点
•使用函数pthread_create(),线程创建后,就开始运行相关的线程函数
退出线程
•在线程函数运行完后,该线程也就退出了
•或使用函数pthread_exit(),这是线程的主动行为
执行结果:
其中的sleep(1) 这一秒 你可以删除试下,你会发现 不会输出任何东西 ,因为sleep(1)后 是 return 0 相当于 exit(0)进程就直接退出了,线程无法脱离其附属进程,当其附属进程消失,线程也自然会跟着消失。
等待线程
•由于一个进程中的多个线程是共享数据段的,通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放
•pthread_join()函数
类似进程的wait()/waitpid()函数,用于将当前线程挂起来等待线程的结束
是一个线程阻塞的函数,调用它的线程一直等待到被等待的线程结束为止
函数返回时,被等待线程的资源就被收回
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>
pthread_t pth1_id,pth2_id;
void *fun1(void *arg)
{
int i=3;
while(i--)
{
printf("pthread1 is running \n");
sleep(1);
}
pthread_exit((void *)1);
//return 0;
}
void *fun2(void *arg)
{
int i=5;
while(i--)
{
printf("pthread2 is running \n");
sleep(1);
}
pthread_exit((void *)2);
}
int main()
{
void *tmp;
if(pthread_create(&pth1_id,NULL,fun1,NULL)!=0)
{
printf("Create thread1 error ! \n");
}
if(pthread_create(&pth2_id,NULL,fun2,NULL)!=0)
{
printf("Create thread2 error ! \n");
}
printf("waitting pthread1 end....\n");
if(pthread_join(pth1_id,&tmp)!=0)
{
printf("joining1 error! \n");
}
printf("pthread1 exit ret is %d\n",(int *)tmp);
printf("waitting pthread2 end....\n");
if(pthread_join(pth2_id,&tmp)!=0)
{
printf("joining2 error! \n");
}
printf("pthread2 exit ret is %d\n",(int *)tmp);
sleep(1);
return 0;
}
从运行结果可以看出pthread_join 是一个阻塞函数。