目录

一、线程的基本概念与特征

1. 什么是线程?

2. 核心特征

二、线程与进程的区别

三、线程编程步骤与查看命令

四、线程核心函数(POSIX 标准)

1. 创建线程:pthread_create

2. 获取当前线程 ID:pthread_self

3. 线程退出

五、线程空间的回收

方式一:阻塞回收(pthread_join)

方式二:分离属性(pthread_detach)

六、总结


 

一、线程的基本概念与特征

1. 什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享该进程的资源。

  • 作用:实现并发,处理相对耗时的任务(比如网络请求、大文件读写等)。

2. 核心特征

  • 进程是系统中最小的资源分配单位。

  • 线程是系统中最小的执行单位。

  • 在同一进程中,线程与线程之间是平级关系。

  • 进程在启动时,默认会有一个线程,称为主线程。

二、线程与进程的区别

对比维度进程(Process)线程(Thread)
资源分配资源独立,拥有独立的虚拟地址空间(如 3GB 空间)。共享进程资源(代码、全局数据、堆、文件描述符),但拥有自己独立的栈区(默认 8MB)。
创建开销非常大(需要分配完整的虚拟地址空间)。相对较小(只需在进程空间中额外开辟一个新的栈区)。
并发度相对较低。并发度高于进程(共享资源,切换开销小)。
稳定性非常稳定。进程之间互不干扰,一个进程崩溃不影响另一个。相对不稳定。如果进程中存在多个线程,其中一个线程崩溃,整个进程都会跟着崩溃。

线程与进程的关系:一个进程可以包含多个线程,线程依附于进程而存在。

三、线程编程步骤与查看命令

POSIX 线程(pthread)编程的三步曲:

  1. 创建多线程
  2. 线程空间操作(执行任务)
  3. 线程资源回收(注意:线程退出后,默认栈区不释放,必须手动回收)

查看系统中线程信息的命令:

# 可以查看轻量级进程(LWP)的信息
ps -eLo pid,ppid,lwp,stat,comm
ps -eLf

四、线程核心函数(POSIX 标准)

使用线程库需要包含头文件 <pthread.h>,并且在编译时必须加上 -pthread 参数(例如:gcc thread.c -o thread -pthread)。

1. 创建线程:pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
  • 参数:

    • thread:传出参数,用于保存创建成功后的线程 ID。
    • attr:线程属性,一般填 NULL 表示默认属性。
    • start_routine:回调函数(函数指针)。本质上是一个函数的名称,是子线程要执行的代码空间。
    • arg:传递给回调函数的参数。
  • 返回值:成功返回 0,失败返回错误码。

2. 获取当前线程 ID:pthread_self

pthread_t pthread_self(void);
  • 功能:获取当前线程的线程 ID(数据类型是 unsigned long int,打印时用 %lu)。

3. 线程退出

线程有多种退出方式:

  • 自行退出:pthread_exit

    void pthread_exit(void *retval);

    参数 retval 是线程退出时的返回状态(临死遗言),可以通过资源回收函数接收。

  • 被动退出:pthread_cancel
    int pthread_cancel(pthread_t thread);

    功能:请求结束一个指定的线程。

五、线程空间的回收

这是多线程编程中非常容易出问题的地方。新线程退出后,其占用的栈区资源默认不会自动释放(类似于进程中的僵尸进程)。

方式一:阻塞回收(pthread_join)

int pthread_join(pthread_t thread, void **retval);
  • 功能:阻塞等待指定的线程结束,并回收其资源。
  • 参数:
    • thread:要回收的子线程 ID。
    • retval:接收子线程退出的返回值(接收 pthread_exit 传出来的数据)。
  • 注意:如果指定的线程没结束,调用该函数的线程(通常是主线程)会一直阻塞。

方式二:分离属性(pthread_detach)

如果主线程很忙,没空去阻塞等待子线程结束,我们可以给子线程设置分离属性。

  • 核心目的:设置分离属性后,当子线程消亡时,系统会自动回收它的空间。
  • 函数定义:
    int pthread_detach(pthread_t thread);
  • 使用方式:可以在子线程内部自己调用 pthread_detach(pthread_self());,也可以由主线程在创建后立即调用。

六、总结

  1. 线程是调度的最小单位,进程是资源分配的最小单位。
  2. 线程共享进程资源,但拥有独立的栈;线程轻量、切换快、并发高,但一个线程崩溃会导致整个进程崩溃(稳定性差)。
  3. 创建线程用 pthread_create。
  4. 线程退出用 pthread_exit。
  5. 回收线程资源:要么用 pthread_join 阻塞等待;要么用 pthread_detach 设置分离属性,让系统自动回收。

 

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐