博客内容:线程
在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”一切进程至少都有一个执行线程,线程在进程内部运行,本质是在进程地址空间内运行在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。
在Linux中是没有线程这个说法的,线程都是使用进程来进行模拟的,在Linux中叫做轻量级进程(LWP)。对于LWP来说,它的执行粒度更小。
在Linux中LWP使用的就是进程的pcb,共享一块地址空间。线程是进程的一个执行分支,所以对于线程来说一旦出现异常,像除零、野指针的问题出现,进程也会随之出现崩溃。
**进程可以实现对于资源的分配,也是资源分配的基本单位。线程存在于进程中作为调度的基本单位。**线程共享进程的数据,但是线程也拥有自己的ID、一组寄存器、独立的栈空间,errno,信号屏蔽字,调度优先级。简单的说就是以前一个工程的所有项目是一个人负责,线程的出现就减轻了工作量,提高了效率。
进程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
- 文件描述符表
- 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
- 当前工作目录
- 用户id和组id
对于进程和进程的关系可以参考一下阮一峰大佬的这篇博客《进程与线程的一个简单解释》 十分形象。
pthread库是一个原生线程库,在Linux中是会自带的,且线程接口函数的返回值都是成功返回0,失败返回-1。在编译时需要带-lpthread,使用函数接口
#include
int pthread_create
(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg
);
参数介绍:参数一作为线程的名称,第二个参数是线程的属性,一般 设置为null,第三个参数是线程执行的函数,第四个参数,作为传入执行函数的参数。
#include
void pthread_exit(void *retval);
参数介绍:类似于exit,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。终止调用它的线程并返回一个指向某个对象的指针,该返回值可以通过pthread_join函数的第二个参数得到。
int pthread_cancel(pthread_t thread);
也可以通过线程的ID来取消执行中的线程。
pthread_t pthread_self(void);
线程的ID获取函数
int pthread_join(pthread_t thread, void **value_ptr);
参数:线程ID、可以是pthread_exit的值,也可以设置null。调用该函数的线程将挂起等待,直到id为thread的线程终止。
线程和进程类似,如果结束后没有被释放,任然会在地址空间内,新的线程不会复用刚才的退出线程的空间。
int pthread_detach(pthread_t thread);
参数:线程ID。默认创建的线程都是joinable的,线程结束后,需要进行pthread_join操作,避免内存泄漏。但是使用pthread_join是有一定的消耗的,如果不管线程的退出结果的话可以使用该函数来自动释放资源。
对于线程来说可以分离其他目标线程,也可以自己分离自己。但是使用这个函数就不能使用函数pthread_join。俩会冲突。
创建一个新线程的代价要比创建一个新进程小得多 。 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多 线程占用的资源要比进程少很多 能充分利用多处理器的可并行数量 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现 I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。