Skip to main content

Rust 并发基础

本章主要讲:

  • Rust 如何创建线程
  • 线程相关的基础概念

读写锁

由于 Mutex 只关注互斥的访问, 需要一种机制来保证可以让多个读者进入, 或只让一个写者进入, 这种情况就需要读写锁. Rust 标准库提供了 RwLock<T> 类型用于这样的场景.

RwLock 的 API 和 Mutex 有不同, 它提供了 readwrite 两个方法分别用于读者和写者, 且分别获取到 RwLockReadGuardRwLockWriteGuard. 前者只实现了 Deref, 后者实现了 DerefMut. 这样被保护的数据就可以分别用于只读和写, 可以将其视作 RefCell 的多线程版本.

RwLock<T> 需要 T 的类型是 SendSync 的, 即类型是可以安全地跨线程传递所有权.

Rust 标准库中的读写锁是和平台相关的, 且绝大部分实现都会在 writer wait 的时候阻塞新的 reader, 及时现在已经是 reader lock 的状态, 这样可以避免 writer 饥饿.

等待条件: 线程 Parking 和条件变量

当数据被多个线程改变, 许多情况下需要这些线程等待某些事件以及某些数据条件变为 true. 比如通过 mutex 保护的 Vec, 我们希望等待它里面包含了数据后再进行处理. 如果我们只使用 Mutex, 则需要我们持续去检查 Vec 是否有数据然后再决定是否解锁.

Thread Parking

thread parking 是让某个线程等待另外一个线程通知的机制. 某个线程可以 park 它自己, 让自己睡眠, 从而避免浪费 CPU 资源. 当条件允许时, 另外一个线程可以将这个休眠的线程唤醒(unpark).

在标准库中有 parkunpark 两个函数用于此目的.