Concurrent
线程
- 独立寄存器
- 共享地址空间
- 使用线程控制块 Thread Control Block 维护状态
- 独立栈空间(Thread Local)
线程 API
- 创建
- 完成(join)
- 互斥量
- 条件变量
线程安全
- 临界区(访问共享资源的代码)
- 竞态条件(多个线程进入临界区)
- 互斥执行
- 原子操作
锁
Pthread 锁(mutex)
特性
- 提供互斥
- 公平性
- 性能
原子指令
- test-and-set
- compare-and-set
- fetch-and-set
自旋锁
需要主动让出 CPU 以避免其他线程饿死
提示:更多并发不一定更快
如果方案带来了大量的开销(例如,频繁地获取锁、释放锁),那么高并发就没有什么意义。如果简单的方案很少用到高开销的调用,通常会很有效。增加更多的锁和复杂性可能会适得其反。话虽如此,有一种办法可以获得真知:实现两种方案(简单但少一点并发,复杂但多一点并发),测试它们的表现。毕竟,你不能在性能上作弊。结果要么更快,要么不快。
信号量
- 二值信号量(锁)
- 信号量可作为条件变量
- 生产者/消费者问题(有界缓冲区)
- 哲学家就餐
常见并发问题
非死锁缺陷
- 违反原子性缺陷
- 违反顺序缺陷
死锁缺陷
产生死锁的条件
- 互斥
- 占有并等待
- 非抢占
- 循环等待
预防和避免死锁
- 避免循环等待
- wait-free 数据结构
- 检查和回复
基于事件的并发
node.js
事件循环
- select(poll)
- 异步 I/O
- 状态管理