Mutex in JavaScript/TypeScript
Examples of mutexes.
Published: 6/21/2024Initialise a mutex as needed on your class; use;
TypeScript#
// FILE: mutex.ts
class Mutex {
private _locking: Promise<void>;
private _locked: boolean;
constructor() {
this._locking = Promise.resolve();
this._locked = false;
}
isLocked(): boolean {
return this._locked;
}
lock(): Promise<() => void> {
this._locked = true;
let unlockNext: () => void;
let willLock = new Promise<void>((resolve) => (unlockNext = resolve));
willLock.then(() => (this._locked = false));
let willUnlock = this._locking.then(() => unlockNext);
this._locking = this._locking.then(() => willLock);
return willUnlock;
}
}
export default Mutex;
Usage:
nextIdMutex = new Mutex();
// read and decrement id
public async takeNextId() {
const unlock = await this.nextIdMutex.lock();
let id: number = 0;
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
console.log('waiting');
resolve();
}, 10000);
});
id = await this.storage?.get('nextId');
await this.storage?.set('nextId', id - 1);
} catch (err) {
console.log(err);
}
unlock();
return id;
}
- Create the mutex
- For critical section
- await lock and save to unlock
- do critical work
unlock()
- I added a blocking promise inside to help prove it works
JavaScript#
class Mutex {
constructor() {
this._locking = Promise.resolve();
this._locked = false;
}
isLocked() {
return this._locked;
}
lock() {
this._locked = true;
let unlockNext;
let willLock = new Promise(resolve => unlockNext = resolve);
willLock.then(() => this._locked = false);
let willUnlock = this._locking.then(() => unlockNext);
this._locking = this._locking.then(() => willLock);
return willUnlock;
}
}
export default Mutex;