Web Lock

The Web Lock API enforces mutual exclusion (i.e. mutex) for concurrency due to multiple workers, tabs or asynchronous functions running scripts from the same origin at the same time. While a lock is held, requests for the same lock from this execution context, or from other tabs/workers, will be queued. The first queued request will be granted only when the lock is released.

Request an "exclusive" lock when it should only be held by one code instance at a time. This applies to code in both tabs and workers. Use this to represent mutually exclusive access to a resource. When an "exclusive" lock for a given name is held, no other lock with the same name can be held.

Request a "shared" lock when multiple instances of the code can share access to a resource. When a "shared" lock for a given name is held, other "shared" locks for the same name can be granted, but no "exclusive" locks with that name can be held or granted.

If 'ifAvailable' is true, the lock request will only be granted if it is not already held. If 'steal' is true, then any held locks with the same name will be released, and the request will be granted, pre-empting any queued requests for it.
await do_something_without_lock();

// Request the lock.
await navigator.locks.request('my_lock',  {mode: 'shared', ifAvailable:false, steal:false},  async lock => {  
   // The lock has been acquired.
   await do_something_with_lock(); 
});
// The lock has been released.
await do_something_else_without_lock();
This returns a Promise that resolves with a LockManagerSnapshot which contains information about held and pending locks.
const state = await navigator.locks.query();
for (const lock of state.held) {
  console.log(`held lock: name ${lock.name}, mode ${lock.mode}`);
}
for (const request of state.pending) {
  console.log(`requested lock: name ${request.name}, mode ${request.mode}`);
}