A read-write lock lets any number of readers share a resource at the same time, but gives a writer exclusive access — no other readers, no other writers — for as long as it holds the lock. It is the standard tool for a resource that is read often and written rarely: reads never conflict with each other, so forcing them to run one at a time (as a plain mutex would) wastes throughput. The catch is fairness. If readers keep arriving and you always let them in, a writer can wait forever. This question is about getting the sharing right and keeping the writer from starving.
Implement asyncRwlock(). It returns a lock with two methods. acquireRead() and acquireWrite() each return a Promise that resolves to a release function once the caller is allowed to proceed; the caller does its work, then calls release() to hand the lock back.
function asyncRwlock(): {
// resolves to release() once a read slot is granted (many may hold at once)
acquireRead(): Promise<() => void>;
// resolves to release() once the lock is held exclusively (no one else holds)
acquireWrite(): Promise<() => void>;
};
const lock = asyncRwlock();
const r1 = await lock.acquireRead(); // granted right away
const r2 = await lock.acquireRead(); // also granted — readers do not block readers
// ...both read the shared value concurrently...
r1(); // release
r2(); // release
const lock = asyncRwlock();
const reader = await lock.acquireRead(); // a reader is holding
const writing = lock.acquireWrite(); // writer must wait for the reader
const late = lock.acquireRead(); // arrives AFTER the writer -> queues behind it
reader(); // reader leaves -> the WRITER runs next, not the late reader
const release = await writing;
release(); // writer leaves -> only now does the late reader run
acquireRead / acquireWrite resolves to its own release function; calling it frees only that one hold.release().