Skip to content
Updated:

大宝典-操作系统

Table of contents

Open Table of contents

258. 0.1 + 0.2 !== 0.3

详见 关于 0.1 + 0.2 !== 0.3 的问题

259. 线程 vs 进程

线程和进程是操作系统中管理任务执行的两个基本概念。

定义

  1. 进程(Process)

    • 定义:进程是一个正在运行的程序实例,它包含了程序代码和当前活动。每个进程都有自己的内存空间、文件描述符等系统资源。
    • 独立性:进程之间是独立的,它们有各自的地址空间,一个进程的崩溃不会影响另一个进程。
    • 开销:创建和销毁进程的开销较大,因为需要分配和回收大量资源。
  2. 线程(Thread)

    • 定义:线程是进程内的一个执行流。一个进程可以包含多个线程,它们共享进程的资源(如内存、文件句柄等),但每个线程有自己的栈和寄存器。
    • 共享资源:线程之间可以直接共享进程的资源,因此通信和数据共享更加高效。
    • 开销:创建和销毁线程的开销相对较小,因为线程之间共享大量资源。

比较

特性进程线程
地址空间独立的共享的
资源共享不共享共享
创建开销较大较小
通信开销通过 IPC(管道、消息队列等)直接共享内存
独立性独立非独立,同一进程的线程影响相互
崩溃影响一个进程崩溃不会影响其他进程一个线程崩溃可能导致整个进程崩溃
使用场景独立应用程序同一应用的多个任务

适用场景

总结

260. 内存中的堆(Heap)和栈(Stack)

栈(Stack)

特点

  1. 内存分配:栈内存由编译器自动管理。当函数被调用时,其局部变量、函数参数和返回地址等信息会被压入栈中。当函数调用结束时,这些数据会从栈中弹出。
  2. 存储数据类型:通常用于存储局部变量和函数调用信息。
  3. 内存管理:栈的内存分配和释放速度快,因为其采用的是后进先出(LIFO, Last In First Out)原则。
  4. 生命周期:栈上的数据在其所属的函数调用结束时会自动销毁。
  5. 大小限制:栈的大小通常较小,由操作系统设定,过大的数据存储可能导致栈溢出(stack overflow)。
void function() {
    int x = 10;  // x 在栈上分配
}

堆(Heap)

特点

  1. 内存分配:堆内存由程序员手动管理,使用动态内存分配函数(如 在 C 语言中 mallocfree ,在 C++ 语言中 newdelete ,或在 JavaScript 中 newdelete )进行分配和释放。
  2. 存储数据类型:通常用于存储需要在函数调用结束后仍然存在的数据,或者需要在运行时决定大小的数据。
  3. 内存管理:堆的内存分配和释放较为复杂,可能会导致碎片化。程序员需要显式地释放不再使用的内存,否则会造成内存泄漏。
  4. 生命周期:堆上的数据在程序员显式释放内存之前会一直存在。
  5. 大小限制:堆的大小通常较大,由系统的虚拟内存大小限制。
void function() {
    int* x = (int*)malloc(sizeof(int));  // x 在堆上分配
    *x = 10;
    free(x);  // 手动释放堆内存
}

比较

特性栈(Stack)堆(Heap)
内存分配由编译器自动管理由程序员手动管理
存储数据类型局部变量、函数参数、返回地址动态分配的数据,需要在函数外部存在的数据
分配/释放速度快(LIFO 原则)慢(需要查找合适的内存块)
内存管理自动(函数结束时自动释放)手动(需要程序员显式释放)
生命周期短暂(函数调用结束时释放)由程序员控制
碎片化无(连续分配)可能有(内存块的分配和释放导致)
大小限制较小(由操作系统设定)较大(由系统虚拟内存限制)

适用场景