news 2026/7/21 7:22:50

南京大学蒋炎岩操作系统笔记(p4-p7)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
南京大学蒋炎岩操作系统笔记(p4-p7)

P4:理解并发程序执行

Model Checker(通用检查器)负责通用任务

  • 枚举所有可达状态

  • 生成并探索状态转移

  • 搜索错误状态

  • 输出状态图

Python Generator(生成器)是后面实现Model Checker的一个关键技术

Generator 可以让一个函数"暂停",下次再从暂停的位置继续执行。

yield会保存整个函数的执行现场(包括局部变量、程序执行位置等)。下一次next()时,会从上一次yield的下一条语句继续执行,而不是重新进入函数。

利用 Generator,Model Checker 可以控制不同线程每次只执行一步,从而模拟不同的线程调度顺序。


P5:并发控制:互斥(自旋锁、互斥锁和futex)

  • lock:保证一条指令原子执行,不会被其他 CPU 或线程打断。

  • xchg:一种原子交换指令,能够一次性完成“读旧值 + 写新值”,常用于实现自旋锁等同步机制。

  • 实际开发通常使用stdatomic.h提供的原子操作接口,而不是直接编写这些汇编指令。

利用xchg原子交换指令实现自旋锁(如果锁被别人占用,就一直在CPU上循环等待,直到锁释放)的代码:

  • int table = YES; void lock() { retry: int got = xchg(&table, NOPE); if (got == NOPE) goto retry; assert(got == YES); } void unlock() { xchg(&table, YES); }

其中YES表示锁是空闲的,NOPE表示锁已经被别人占用

RISC-V原子操作(LR/SC(Load-Reserved / Store-Conditional)

  • LR(Load Reserved) 作用: ① 读取内存数据 ② 对该内存建立 reservation(预约/保留)
  • SC(Store Conditional) 作用: 只有 reservation 未失效时才允许写入。
  • 返回值: 0:写入成功 非0:写入失败(reservation 已失效)
  • reservation 失效条件: 1、其他 CPU/线程修改该内存 2、中断(多数实现会取消 reservation)
  • 实现流程: LR → 本地计算 → SC 成功则完成原子操作; 失败则重新执行 LR/SC,直到成功。

RISC-V 不像 x86 提供 lock add、lock xchg 等专用原子指令

RISC-V 通过LR(预约读取)+ SC(条件写回)实现原子操作,若期间数据被其他处理器修改,则 SC 失败,需要重新尝试。

自旋锁的缺陷:

① 缓存同步开销 - 多个 CPU 不断访问同一个锁变量。 - 会触发缓存一致性(Cache Coherence),增加通信延迟,降低性能。

② CPU空转- 获得锁的线程执行临界区。 - 其他线程一直 while 循环等待(自旋),占用 CPU 但不做有效工作。 - 竞争线程越多,CPU 利用率越低。

③ 持锁线程被切换 - 持有锁的线程可能被操作系统切换出去。 - 其他线程持续自旋等待,无法进入临界区。 - 造成 CPU 100% 占用但没有有效工作,资源严重浪费

自旋锁的使用场景:操作系统内核的并发数据结构(短临界区

实现长临界区的互斥:长临界区不适合一直自旋,而是采用“阻塞 + 唤醒”机制。

流程: ① 获得锁的线程进入临界区。 ② 后来的线程加入等待队列,并调用 yield() 主动让出 CPU。 ③ 持锁线程释放锁后,唤醒等待队列中的一个线程;若无人等待,则释放锁。

自旋锁(Spin Lock)

优点:

  • 获取锁很快
  • 不需要系统调用

缺点:

  • 获取不到锁就一直自旋,浪费 CPU。

睡眠锁(Mutex)

优点:

  • 获取不到锁就睡眠,不浪费 CPU。

缺点:

  • 每次加锁、解锁都可能进入内核(系统调用),开销较大。

Futex(Fast Userspace Mutex)=自旋锁+睡眠锁

核心思想: 先在用户态尝试获取锁,只有竞争时才进入内核。

工作流程: ① 获取锁成功:用户态完成,无系统调用(Fast Path)。 ② 获取锁失败:调用 futex(),进入内核睡眠等待(Slow Path)。 ③ 解锁:若有等待线程,调用 futex_wake() 唤醒;否则直接释放锁。

优点: 无竞争时无需系统调用,速度快。 有竞争时线程睡眠,不会一直自旋浪费 CPU。

Fast Path: 用户态完成加锁/解锁,无系统调用。

Slow Path: 锁竞争时进入内核,睡眠和唤醒线程。

注意: Futex 实现复杂,容易出现竞争、死锁、丢失唤醒等问题,因此常借助 Model Checker 验证其正确性。


P6:并发控制:同步(条件变量、信号量)

在多处理器上协同多个线程完成任务。

线程同步:在某个时间点共同达到互相已知的状态(因为并发程序的步调很难保持一致,所以需要先到的先等)

经典线程同步问题:生产者-消费者模型

  • 生产者:生成数据,并放入共享缓冲区。
  • 消费者:从共享缓冲区取出数据并处理。
  • 缓冲区:两者共享的有限空间。

也就是不断重复尝试,属于忙等待,会浪费 CPU。更合理的方式是使用条件变量信号量,让缓冲区满或空时线程阻塞睡眠。

1、条件变量(万能同步方法)

条件变量通常用于在某个线程等待特定条件的满足时,将其挂起,并在其他线程满足条件时唤醒它。条件变量提供了一种有效的方式来实现线程之间的通信,以及在某个条件成立时阻塞和唤醒线程。

2、信号量(Semaphore)

信号量是一种基于计数器的同步机制,用于控制多个线程对有限资源的访问,也可实现线程同步。线程通过P(wait)V(signal)操作申请和释放资源。

  • P(wait):信号量减 1;若结果小于 0(或资源不足),线程阻塞等待。
  • V(signal):信号量加 1;若有等待线程,则唤醒其中一个线程。

特点:

  • 内部维护一个计数器
  • 可实现互斥(初值为 1,称二值信号量)。
  • 可实现资源管理(初值大于 1,表示可同时访问的资源数量)。
  • 常用于生产者—消费者问题、读者—写者问题等同步场景。

P7:真实时间的并发编程(高性能计算/数据中心/人机交互中的并发编程)

数据中心特点:低延迟、有备份、能同步

线程(Thread)

特点:

  • 操作系统调度
  • 多个线程共享同一进程地址空间。
  • 可以真正利用多核 CPU并行执行。
  • 获取共享资源时需要使用Mutex、信号量、条件变量等同步机制。

优点:

  • 能充分利用多核 CPU。
  • 适合计算密集型任务。

缺点:

  • 线程切换开销较大。
  • 容易出现竞争、死锁等并发问题。

协程(Coroutine)

特点:

  • 程序自身调度
  • 在用户态完成切换。
  • 遇到yieldawait时主动让出执行权。
  • 一个线程中可以运行多个协程。

优点:

  • 切换速度快。
  • 开销小。
  • 编程简单,不容易产生线程竞争。

缺点:

  • 通常不能充分利用多核 CPU。
  • CPU 密集型任务性能不如多线程。

Go语言能像线程一样利用多核,也能像协程一样轻量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 7:17:30

5分钟搭建京东抢购脚本:告别手动秒杀烦恼的终极指南

5分钟搭建京东抢购脚本:告别手动秒杀烦恼的终极指南 【免费下载链接】JDspyder 京东预约&抢购脚本,可以自定义商品链接 项目地址: https://gitcode.com/gh_mirrors/jd/JDspyder 还在为京东茅台、热门商品秒杀抢不到而烦恼吗?JDspy…

作者头像 李华
网站建设 2026/7/21 7:16:53

HALCON 图像平滑处理算子原理解释与用处

文章目录概要整体架构流程技术名词解释技术细节概要 在HALCON中,为了更好的处理图片,我们通常会对图片进行平滑处理,以减少图片噪点对我们工作的干扰,那么HALCON中图片平滑处理算子的原理是如何运作,参数如何调配&…

作者头像 李华
网站建设 2026/7/21 7:16:22

京东抢购自动化终极指南:JDspyder脚本让秒杀成功率翻倍

京东抢购自动化终极指南:JDspyder脚本让秒杀成功率翻倍 【免费下载链接】JDspyder 京东预约&抢购脚本,可以自定义商品链接 项目地址: https://gitcode.com/gh_mirrors/jd/JDspyder 还在为抢不到京东热门商品而烦恼吗?JDspyder京东…

作者头像 李华
网站建设 2026/7/21 7:14:34

JAVAEE初阶 --- 构造HTTP请求

本文将重点介绍如何构造 HTTP 请求和构造 HTTP 请求的几种方法。 方法一:通过 form 表单构造 HTTP 请求(纯 HTML 文案) 方法二:通过 ajax 构造 HTTP 请求(通过 javascript 构造 HTTP 请求) 方法三&#…

作者头像 李华