class Semaphore { constructor(max) { this.tasks = []; this.counter = max; this.dispatch = this.dispatch.bind(this); } dispatch() { if (this.counter > 0 && this.tasks.length > 0) { this.counter--; this.tasks.shift()(); } } release() { this.counter++; this.dispatch(); } acquire() { return new Promise(res => { this.tasks.push(res); setTimeout(this.dispatch, 100); }); } } var semaphore = new Semaphore(2); var run = (async() => { await semaphore.acquire(); console.log('first runner'); await semaphore.acquire(); console.log('second runner'); await semaphore.acquire(); console.log('third runner'); })();