from mosaic import *
OS2023(12)
12. 真实世界的并发 Bug¶
Changelog & 反馈
- QEMU 的 monitor 哪去了?
- Mandelbrot set or Julia set? (我找助教检查了,但助教竟然还没有回我)
- 修复了同学提出的 typo (欢迎大家提出任何问题,包括意见和建议)
背景回顾:当我们在写程序的时候,我们其实是在写 bug。时至今日,我们还没有有效、方便的技术能帮助我们快速构建可靠的软件系统。然而并发 bugs “若隐若现” 的特性又导致它们经常逃脱开发人员的掌控。
本讲内容:常见的并发 bugs
- 死锁
- 数据竞争
- 原子性和顺序违反
slideshow('12.1')
这个事故告诉我们:在安全攸关的系统中,独立的防护模块是必不可少的。依据调试理论,即便不是安全攸关的系统,独立于程序实现的逻辑检查 (assertions) 可以在软件造成问题之前 fail fast。
slideshow('12.2')
model('m/deadlock-aa.py', check=True)
slideshow('12.3')
demo('peterson', 'c/peterson.c', libs=['thread.h'])
slideshow('12.4')
# This is a "process-level" race
model('m/tocttou.py', check=True)
“原子性” 一直是开发者希望拥有的——对编程者而言,理想情况是一段代码的执行要么看起来在瞬间全部完成,要么好像完全没有执行过。代码中的副作用:共享内存写入、文件系统写入等,则都是实现原子性的障碍。因为 “原子性” 如此诱人,在计算机硬件/系统层面提供原子性的尝试一直都没有停止过:从数据库事务 (transactions, tx) 到软件和硬件支持的 Transactional Memory “an idea ahead its time” 到 Operating System Transactions,直到今天我们依然没有每个程序员都垂手可得的可靠原子性保障。
而保证程序的执行顺序就更困难了。Managed runtime 实现自动内存管理、channel 实现线程间通信等,都是减少程序员犯错的手段。
Take-away Messages¶
人类本质上是 sequential creature,因此总是通过 “块的顺序执行” 这一简化模型去理解并发程序,也相应有了两种类型的并发 bugs:
- Atomicity violation,本应原子完成不被打断的代码被打断
- Order violation,本应按某个顺序完成的未能被正确同步
与这两类 bugs 关联的一个重要问题是数据竞争,即两个线程同时访问同一内存,且至少有一个是写。数据竞争非常危险,因此我们在编程时要尽力避免。
课后习题/编程作业¶
1. 阅读材料¶
教科书 Operating Systems: Three Easy Pieces:
- 第 32 章 - Concurrency Bugs