同步原语
前面几部分里,叫醒任务的是驱动:socket 可读了,定时器到期了。tokio::sync 里的东西是另一种唤醒来源:一个任务 send、unlock、notify,另一个任务被叫醒。它们不依赖运行时的驱动,源码都在 sync/ 下,大部分在运行时之外也能用。
这一部分讲三件事:
- batch_semaphore:一个原子计数加一条侵入式等待链表。
Semaphore、Mutex、RwLock和有界mpsc的背压都建在它上面。只要有人在排队,计数就是 0,所以先来的一定先拿到。 - mpsc:发送端用一次
fetch_add抢一个序号,写进 32 槽一块的链表;接收端独占链表头,读完的块尽量挂回尾部复用。有界和无界只差一个Semaphore实现。 - oneshot、watch、broadcast、Notify:一个状态字的 oneshot;版本号加读写锁的 watch;环形缓冲区的 broadcast;以及
Notify到底会不会丢通知。
flowchart TB bs[batch_semaphore] --> sem[Semaphore] bs --> mutex["Mutex:1 个许可"] bs --> rw["RwLock:读 1 个,写全部"] bs --> bounded[有界 mpsc 的背压] list[block 链表] --> bounded list --> unbounded[无界 mpsc] notify[Notify] --> watch["watch:8 个 Notify"] notify --> closed["mpsc 的 closed()"] ring[环形缓冲区] --> bc[broadcast] state[一个状态字] --> os[oneshot]
这些原语的 future 大多会扣协作式预算(Notify 除外),预算本身见协作式调度预算。tokio::sync::Mutex 和 std::sync::Mutex 怎么选,放在「常见坑」里。
💬 关联讨论
发起讨论加载中...