1、概念:进程内部的一条执行序列(执行流) 线程时轻量级的进程,一个进程中至少有一条线程
执行序列: 一组有序指令+数据的集合 以函数为单位
main函数所代表执行序列,称之为主线程。通过线程库创建线程---函数线程
主线程和函数线程没有本质区别,只是主线程是进程执行时第一个执行的线程
线程与进程:
1、进程是资源分配的单位,线程是CPU调度执行的单位
2、进程是线程的集合,进程中包含数据、资源,一个进程中所有线程共享进程的数据、资源
3、线程创建、调度相比较于进程更加轻巧
2、线程库的使用:
创建: int pthread_create(pthread_t *id,pthread_attr_t *attr, void* (*pthread_fun)(void*),void *arg)
id:create函数通过id返回线程的id
attr:线程的属性,默认NULL
pthread_fun:线程函数 创建的线程执行的函数(一组有序指令)
arg:传递给函数线程所执行的函数参数(以下两种方法)
1)值传递(只能应用于小于等于4字节的数据) ----> 将数值转化为void*
2)地址传值 ----> 将变量的地址转化为void *(函数调用中*(void*))
成功返回0,失败返回错误码
函数线程中通过传递形参对变量的修改,会造成主线程值也随之修改
主线程中对变量的修改,也会造成函数线程中值的修改
主线程退出:main函数结束,main函数结束默认会调用exit(0) ---> 进程结束
创建线程:int pthread_create();
线程结束的函数:pthread_exit(void *retval);
等待线程结束函数:pthread_join(pthread_t id,void **retval);//阻塞,直到等待线程结束。获取结束的线程的退出信息
主动结束函数:pthread_cancel(pthread_id);//根据id结束一个线程
3、线程的实现方法:
用户级线程:线程的实现在用户态实现,对于内核,只能识别出其是一个进程。线程的管理有用户态实现。内核实现简单。
优点:切换速度快。
缺点:1、用户代码复杂 2、当一条线程阻塞,会造成整个进程阻塞
内核级线程(Linux):线程的实现在内核态,线程的创建、调度、销毁等管理是由操作系统支持。内核实现复杂,需要多线程支持。
优点:1、用户代码简单2、一条线程阻塞,操作系统可以立马切换到另一条线程,整个进程不会阻塞
缺点:线程切换效率低,线程每次必须陷入内核
混合级线程:线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行. 一个应用程序中的多个用户级线程被映射到一些(小于或等于用户级线程的数目)内核级线程上。
每个内核级线程有一个可以轮流使用的用户级线程集合
4、进程与线程的区别:
- 进程是系统资源分配的最小单位,线程是CPU调度的最小单位
- 线程依赖于进程,线程在进程内部,一个进程至少包含一条线程
- 一个进程可以包含多条线程, 一个线程只能属于一个进程
- 创建线程的代价比创建进程的代价小的多
- 进程的切换效率比线程的切换效率低
- 进程都是独立的个体,同一个进程中的所有线程只有自己的栈区,其他空间共享
- 进程间通讯必须借助特殊的机制,线程则可以直接通过共享的空间(全局空间、或堆区空间)通讯
- 同一个进程中的线程之间存在安全问题, 而不同进程之间不存在
5、多线程的数据共享
1、全局 共享 -----> 虚拟地址相同 同一个进程中的多个线程共享进程的4G虚拟地址空间
2、栈区 不共享 -----> 创建线程时,将栈区数据的地址传递函数线程
3、堆区 共享
4、文件描述符 共享