多线程编程:线程与进程基础

一、线程与进程的核心区别

本质差异

  • 进程是操作系统进行资源分配的基本单位拥有完整的资源集合,包括代码段、数据段、堆、栈、打开的文件句柄等;

  • 线程是CPU调度和执行的基本单位,不拥有独立的资源,依托所属进程的资源运行,仅独占自身的栈空间、寄存器和程序计数器,多个线程共享同一进程的所有资源。

资源共享

  • **进程间的虚拟地址空间相互独立,默认不共享任何资源,**若需实现进程间资源共享,必须借助IPC(进程间通信)机制,常见的有管道、共享内存、消息队列、信号量等;

  • 同一进程内的所有线程,因共享进程的虚拟地址空间,可直接访问进程内的全局变量、堆内存、静态变量、打开的文件等资源,无需额外通信机制。

切换开销

  • 进程切换时,需要切换整个进程的资源上下文 ,包括页表、寄存器、栈、文件句柄等,切换成本高、消耗系统资源多,效率较低;

  • 线程切换仅需切换自身的执行上下文(寄存器、程序计数器、栈指针),无需切换进程资源和页表(线程共享进程页表),切换开销远小于进程,并发效率更高。

稳定性

  • 进程之间相互独立,每个进程拥有独立的地址空间和资源,一个进程的崩溃(如内存错误、异常退出)不会影响其他进程的正常运行;

  • 线程共享进程的资源和地址空间,若一个线程触发内存错误(如野指针、栈溢出),会破坏进程的资源结构和地址空间,导致整个进程及所属所有线程崩溃,稳定性远低于进程。

跨平台差异

  • Windows系统:线程是真正的调度实体,进程仅作为资源分配的单位,不参与CPU调度;主线程从主函数(main函数)开始执行,所有线程均可被操作系统直接调度,存在就绪态、执行态、I/O阻塞态三种基本状态的切换,线程的创建和调度由操作系统内核直接管理。

  • Linux系统:线程本质是轻量级进程(LWP),进程本身也是CPU调度的基本单位;主线程所在的执行体即为进程,其他线程均为该进程的轻量级分支,共享进程的资源和地址空间;线程的调度本质上是轻量级进程的调度,进程切换的资源消耗远大于线程切换,Linux通过clone系统调用创建线程,共享进程的页表、文件描述符等资源。

二、线程数量限制

  • 32位系统限制原因:32位系统的虚拟地址空间总大小为4GB,在Linux系统中,默认1GB分配给内核态,剩余3GB分配给用户态;每个线程都有独立的栈空间,栈空间的大小由系统默认配置(通常为8MB),所有线程的栈空间总和不能超过用户态的3GB虚拟地址空间,因此线程数量由"3GB / 单个线程栈大小"决定。理论上,32位系统的线程数量约为3GB/8MB≈384个,实际数量会更少,因为用户态地址空间还需分配给堆内存、共享库等其他资源,无法全部用于线程栈。

  • 64位系统限制原因:64位系统的虚拟地址空间理论上可达2^64,实际可用的用户态虚拟地址空间约为256TB,远大于实际的物理内存大小,因此线程数量不再受虚拟地址空间的限制。64位系统中,线程数量的核心瓶颈是物理内存大小和CPU调度开销:每个线程的栈空间和线程控制块(TCB)需要占用物理内存,物理内存不足会导致线程创建失败;同时,线程数量过多会导致CPU上下文切换频繁,消耗大量CPU资源,反而降低程序的并发效率,因此线程数量需根据CPU核心数和任务类型合理设置。

三、线程与进程的地址空间特性

  1. 进程间的虚拟地址空间相互独立,每个进程都有自己的页表,将虚拟地址映射到物理地址,进程之间无法直接访问对方的虚拟地址空间,若需通信,必须通过IPC机制实现资源共享或消息传递。

  2. 线程属于某个特定的进程,所有线程共享该进程的虚拟地址空间、页表和物理内存资源,因此线程可直接访问进程内的全局变量、堆内存、静态变量等共享资源;但线程也有自己独立的栈空间,栈空间用于存储线程的局部变量、函数栈帧等,线程之间的栈空间相互独立,互不干扰,避免了线程间的栈数据冲突。

补充:

1.函数被调用时,会在当前线程的栈上开辟独立的栈帧,每调用一次函数就会开辟一块新的栈帧,栈空间的生长方向为"向上"(即从高地址向低地址生长);

2.栈帧的生命周期与函数调用一致,函数执行完毕后,栈帧自动释放,局部变量也随之销毁。

3.线程的栈空间和堆空间有明显区别:

  • 栈空间由系统自动分配和释放,每个线程独有,存储局部变量、函数栈帧;
  • 堆空间由程序员手动分配(如new、malloc)和释放(如delete、free),所有线程共用,存储动态分配的内存,堆空间的生命周期由程序员控制,若未及时释放,会导致内存泄漏。

问题总结:

进程和线程的本质区别是什么?

核心区别是定位不同:

进程是资源分配的基本单位,拥有完整的资源集合(代码段、数据段、堆、栈等);

线程是CPU调度和执行的基本单位,不拥有独立资源,依托所属进程的资源运行,仅独占栈、寄存器、程序计数器。

简单总结为"进程管资源,线程管执行"。

Linux下的线程和Windows下的线程有什么区别?

核心差异在于调度实体和实现方式:

① Windows中,线程是真正的调度实体,进程仅作为资源单位,线程由操作系统内核直接调度;② Linux中,线程本质是轻量级进程(LWP),进程也是调度实体,线程的调度本质是轻量级进程的调度,线程通过clone系统调用创建,共享进程的页表和资源。

32位和64位系统中,线程数量的限制原因分别是什么?

① 32位系统:虚拟地址空间共4GB,用户态仅3GB,每个线程有独立栈空间,线程数量受"3GB / 单线程栈大小"限制,受虚拟地址空间约束;

② 64位系统:虚拟地址空间极大(实际用户态256TB),不受虚拟地址限制,仅受物理内存大小(线程栈和TCB占用物理内存)和CPU调度开销约束。

为什么线程切换比进程切换效率高?

因为切换的上下文不同:进程切换需要切换整个资源上下文(页表、寄存器、栈、文件句柄等),开销大;线程切换仅需切换自身的执行上下文(寄存器、程序计数器、栈指针),无需切换进程资源和页表(线程共享进程页表),因此切换开销远小于进程。

线程的栈空间和堆空间有什么区别?

① 栈空间:每个线程独有,由系统自动分配和释放,存储局部变量、函数栈帧,生长方向从高地址到低地址,生命周期与函数调用一致;

② 堆空间:所有线程共用,由程序员手动分配和释放,存储动态内存,生命周期由程序员控制,未及时释放会导致内存泄漏。

相关推荐
Filwaod1 天前
Java面试现场:从Redis缓存到分布式事务,水货程序员李四的‘表演‘
java·jvm·spring boot·redis·mysql·面试·多线程
Qt程序员2 天前
网络 I/O 面试必考点:从多进程多线程到异步 I/O 与多路复用
linux·网络编程·多线程·epoll·网络io·阻塞io·io_uring
Byron__2 天前
Java并发核心面试知识点
java·面试·多线程·并发编程
兔小盈4 天前
多线程篇-(二)线程创建、中断与终止
java·开发语言·多线程
代码小书生5 天前
电脑下载工具,支持网盘、磁力、种子、直链等多种协议!可多任务、多线程批量下载,适配Windows、Mac、Linux多平台!轻量级设计,系统资源占用小!
多线程·电脑技巧·下载工具·下载速度·电脑知识·下载教程·下载神器
Thanks_ks8 天前
透过 Copy-On-Write 机制:理解并发编程中的性能与一致性权衡
java·多线程·并发编程·底层原理·写时复制·copyonwrite·性能优
苍煜10 天前
多线程同步并行查询-CompletableFuture完整落地方案
多线程
阿昭L11 天前
Windows中的I/O完成通知与事件内核对象
windows·多线程
阿冰冰呀12 天前
互联网大厂Java求职面试实录:谢飞机的“水货”之路
java·mybatis·dubbo·springboot·线程池·多线程·hashmap
CoderMeijun16 天前
C++ 多线程进阶:Lambda、条件变量与死锁
c++·多线程·条件变量·lambda·死锁·生产者消费者