功能说明
该示例让多个异步读者共享访问、写者独占访问成为可能。acquireRead 在无写者且无排队时立即放行,否则排队;acquireWrite 需等待所有读者离开且无写者。释放后由 drain 按队列顺序唤醒,队列里若队首是写者则必须等读者清零,从而避免写者饿死。
关键代码
请求先判断能否立即满足:无排队、无写者,且读者请求只要求当前无写者,写者请求要求读者为零。满足则直接解析并立即返回(由调用方随后自增计数),否则入队等待。drain 只处理队首:写者需读者与写者均为空,读者只需无写者。以队首判断而非扫描整队,保证近似先进先出的公平性。release 更新状态后统一调用 drain。
使用注意
读写锁适合读远多于写的状态;写频繁时其簿记开销可能超过收益,普通互斥更简单。绝不要尝试把读锁就地升级为写锁,本实现不支持,会死锁;应先释放再以写模式重新获取,并重新校验数据。等待者按队首推进,但读者释放后可能连续放行多个读者,这符合设计;若需严格写者优先,应在排队时加入额外策略。
代码示例
export class AsyncReaderWriterLock {
private readers = 0;
private writer = false;
private queue: Array<{ write: boolean; resolve: () => void }> = [];
async acquireRead(): Promise<() => void> {
await this.request(false);
this.readers += 1;
return () => this.release(false);
}
async acquireWrite(): Promise<() => void> {
await this.request(true);
this.writer = true;
return () => this.release(true);
}
private request(write: boolean): Promise<void> {
if (this.queue.length === 0 && !this.writer && (write || this.readers >= 0)) {
if (write ? this.readers === 0 : !this.writer) return Promise.resolve();
}
return new Promise((resolve) => this.queue.push({ write, resolve }));
}
private release(write: boolean) {
if (write) this.writer = false;
else this.readers -= 1;
this.drain();
}
private drain() {
while (this.queue.length > 0) {
const next = this.queue[0] as { write: boolean; resolve: () => void };
if (next.write) {
if (this.writer || this.readers > 0) return;
(this.queue.shift() as { resolve: () => void }).resolve();
return;
}
(this.queue.shift() as { resolve: () => void }).resolve();
}
}
}