AI训练新发现:重复数据训练提升模型效果
2026/7/24 5:47:48
进程是资源分配的基本单位,线程是CPU调度的基本单位。两者创建的核心差异在于:进程创建需分配独立资源(内存、文件描述符等),线程创建仅需分配调度相关的轻量数据结构(TCB、栈),共享所属进程的资源。以下从底层流程、核心数据结构、系统调用三个维度拆解,结合Java开发场景补充关联。
创建一个独立的资源容器,包含运行程序所需的所有资源(内存、文件、IO等),并将其纳入OS的进程调度体系。
fork()系统调用)| 步骤 | 底层操作 | 核心细节 |
|---|---|---|
| 1. 分配进程控制块(PCB) | OS内核在PCB链表中创建新节点 | PCB是进程存在的唯一标识,包含: - 进程ID(PID)、父进程ID(PPID) - 进程状态(就绪/运行/阻塞) - 资源指针(指向内存页表、文件描述符表、打开文件列表) - 调度信息(优先级、时间片、调度队列指针) - 上下文信息(寄存器组、程序计数器PC) |
| 2. 分配独立资源 | (1)内存分配:创建独立的虚拟地址空间,通过页表映射到物理内存(Copy-On-Write 写时复制机制优化:fork()时不直接拷贝父进程内存,仅在子进程修改数据时才拷贝对应页,降低创建开销); (2)文件资源:复制父进程的文件描述符表(指向相同的打开文件),引用计数+1; (3)其他资源:分配PID、信号处理函数、进程优先级等。 | 重点:Copy-On-Write(COW)是进程创建的性能优化核心,避免无意义的内存拷贝(比如父进程仅读数据时,子进程无需单独拷贝)。 |
| 3. 初始化进程状态 | 将PCB中的进程状态设为「就绪态」,初始化程序计数器(PC)为父进程的指令指针(fork()返回后,子进程从父进程当前执行点继续运行),清空CPU寄存器上下文(等待调度器分配CPU时填充)。 | 注:fork()创建的子进程会复制父进程的内存数据(代码段、数据段、堆),但内核栈和用户栈是独立的(避免调度冲突)。 |
| 4. 纳入调度体系 | 将PCB加入OS的就绪队列,等待CPU调度器(如CFS调度器)分配时间片,触发进程上下文切换后开始运行。 | 调度器通过PCB中的优先级、时间片等信息决定调度顺序。 |
fork()(创建子进程,复制父进程资源)+exec()(加载新程序替换子进程内存空间);CreateProcess()(一站式创建进程+加载程序,不区分fork/exec)。创建一个轻量级的调度单元,共享所属进程的所有资源,仅新增调度和执行相关的最小化数据结构,实现「并发执行同一程序」。
pthread_create())| 步骤 | 底层操作 | 核心细节 |
|---|---|---|
| 1. 分配线程控制块(TCB) | 内核创建TCB(Thread Control Block),作为线程的唯一标识 | TCB包含: - 线程ID(TID)、所属进程PID - 调度信息(优先级、时间片、调度策略) - 上下文信息(寄存器组、程序计数器PC) - 栈指针(用户栈+内核栈的地址) - 线程状态(就绪/运行/阻塞) |
| 2. 分配独立栈空间 | (1)用户栈:默认大小为几MB(Linux下默认8MB),用于函数调用、局部变量存储(线程私有,避免数据竞争); (2)内核栈:用于线程陷入内核态时(如系统调用)保存上下文,大小固定(Linux下默认8KB)。 | 重点:线程不分配独立内存空间,共享所属进程的代码段、数据段、堆、文件描述符表、信号处理函数等资源。 |
| 3. 绑定进程与初始化 | 将TCB关联到所属进程的PCB(通过PID绑定),初始化线程状态为「就绪态」,设置线程的调度参数(继承进程的默认优先级)。 | 线程的资源权限完全继承自父进程,无法独立拥有资源(除非显式通过进程分配)。 |
| 4. 纳入调度体系 | 将TCB加入就绪队列,与其他线程(同进程/不同进程)竞争CPU时间片,调度器通过TCB信息进行调度。 | 线程切换开销远小于进程:仅需保存/恢复TCB中的上下文(寄存器、栈指针),无需切换页表(共享进程虚拟地址空间)。 |
pthread_create()(用户态调用,最终通过clone()系统调用创建内核线程);CreateThread();Thread类本质是「操作系统原生线程」(JDK1.2后废弃用户级线程),通过JNI调用底层系统调用:如Linux下调用pthread_create(),Windows下调用CreateThread(),因此Java线程的创建开销=OS内核线程的创建开销。| 对比维度 | 进程创建 | 线程创建 |
|---|---|---|
| 资源分配 | 分配独立资源(虚拟内存、文件描述符表、PCB等) | 不分配独立资源,共享所属进程的所有资源,仅分配TCB和栈 |
| 开销大小 | 开销大(内存拷贝、页表创建、资源初始化) | 开销小(仅初始化TCB和栈,共享资源) |
| 隔离性 | 高(进程崩溃不影响其他进程,资源独立) | 低(线程共享进程资源,一个线程崩溃可能导致整个进程崩溃) |
| 调度粒度 | 粗(CPU切换进程需切换页表,上下文切换开销大) | 细(切换线程无需切换页表,上下文切换开销小) |
| 系统调用 | fork()+exec()(Linux)、CreateProcess()(Windows) | pthread_create()(POSIX)、CreateThread()(Windows) |
newThread(()->System.out.println("Hello")).start();Thread.start()后,JVM通过JNI调用java.lang.Thread#start0()(本地方法);pthread_create()),创建内核线程并绑定TCB;run()方法中的逻辑。