从线程基础到 JS 异步:理解单线程世界的并发逻辑

34 阅读4分钟

线程知识简单回顾

线程是操作系统中独立调度和执行的基本单位,依赖进程存在且共享进程资源,核心作用是提升程序并发执行效率。

一、线程的核心定义与本质

  • 线程是进程内的 “轻量级执行流”,一个进程可包含多个线程。
  • 线程自身仅保留少量必要资源(如程序计数器、寄存器组、栈),其余资源(如内存空间、文件句柄)与同进程内其他线程共享。
  • 操作系统调度的最小单位是线程,而非进程,调度切换开销远低于进程。

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

  1. 资源占用:进程是资源分配的基本单位,线程不独立分配资源,共享进程资源。
  2. 调度开销:线程切换无需切换地址空间,开销小;进程切换需切换地址空间,开销大。
  3. 独立性:进程间相互独立,一个进程崩溃不影响其他进程;同进程内线程高度依赖,一个线程崩溃可能导致整个进程终止。

单线程之Javascript

JavaScript 是单线程的 —— 同一时间只能执行一段代码。这一特性让异步执行成为 JS 的核心能力,否则像网络请求、定时器这类耗时操作会直接卡住整个程序。要理解 JS 的运行逻辑,首先要分清同步代码异步代码的执行规则。

示例 1:同步与异步的基础区别
<script>
  // 异步任务:3秒后执行回调函数
  setTimeout(function() {
    console.log(2);
  }, 3000);
  // 同步任务:立即执行
  console.log(3);
</script>

执行顺序:3 → 等待 3 秒 → 2。原因:同步代码(console.log(3))会按顺序立即执行;而异步任务(setTimeout)会被暂时挂起,等所有同步代码执行完,再在指定时间后运行回调。

示例 2:Promise 与异步任务的优先级
<script>
  console.log(1); // 同步代码:立即执行
  // Promise 构造函数内的代码是同步执行的,但 then 回调属于异步微任务
  const p = new Promise((resolve) => {
    // 嵌套的 setTimeout 是异步宏任务,3秒后执行
    setTimeout(function() {
      console.log(2); 
      resolve(); // 触发 then 回调
    }, 3000);
  });
  // then 回调:属于异步微任务,优先级高于宏任务
  p.then(() => {
    console.log(3);
  });
  console.log(4); // 同步代码:立即执行
</script>

执行顺序:1 → 4 → 2 → 3image.png

这里的深层原因为:

  1. 同步代码优先:先执行 console.log(1) 和 console.log(4),输出 1 和 4

  2. 异步任务分类型

    • setTimeout 属于宏任务(优先级低),3 秒后执行其回调,输出 2
    • p.then 属于微任务(优先级高),在宏任务执行后立即触发,输出 3

这一流程由 JS 的事件循环(Event Loop)  机制控制:同步代码执行完毕后,先清空所有微任务,再执行一个宏任务,以此循环,保证异步操作有序进行。

Promise: 异步编程的 “高级工具

Promise 是 ES6 引入的异步编程解决方案,它的设计目的是让异步代码的执行流程更可控,解决了传统回调函数 “嵌套地狱” 的问题,让异步逻辑可以像同步代码一样清晰。 造方式new Promise 接受一个函数作为参数(这个函数称为 “执行器”),执行器会立即执行,用于启动异步任务。

const p = new Promise((resolve, reject) => {
  // 这里写异步任务(如网络请求、定时器)
  setTimeout(() => {
    // 异步任务成功时,调用 resolve()
    resolve('任务完成');
    // 异步任务失败时,调用 reject()
    // reject('任务失败');
  }, 1000);
});
  • 状态与回调

    • resolve():表示异步任务成功完成,会触发 .then 里的函数执行。
    • reject():表示异步任务失败,会触发 .catch 里的函数执行。
  • 流程控制:通过 .then 方法可以按顺序控制异步流程,前一个异步任务完成后,再执行下一个任务,避免了回调嵌套。

总结

JavaScript 的单线程特性,看似限制了执行效率,却通过事件循环、Promise 等机制构建了独特的异步编程模型,让复杂的并发操作变得可控且清晰。从线程的基础概念到 JS 中宏任务与微任务的优先级调度,核心逻辑始终围绕 “如何在有限的执行资源中,高效处理多任务”。理解这些原理,不仅能帮助我们写出更符合运行机制的代码,更能深入悟编程语言在设计时对性能与逻辑清晰性的平衡智慧。无论是多线程环境的资源共享,还是单线程下的异步协作,本质上都是对 “并发” 这一核心问题的不同解答 —— 而掌握这些解答,正是我们提升编程能力的关键一步。