js 实现同步锁
同步锁的概念
在JavaScript中,由于单线程和事件循环机制,传统的多线程同步锁概念并不直接适用。但通过Promise、Async/Await或共享状态管理,可以模拟类似同步锁的行为,控制异步代码的执行顺序。
使用Promise实现同步锁
通过Promise链和闭包维护锁状态,确保异步操作按顺序执行:
class Lock {
constructor() {
this._locked = false;
this._queue = [];
}
acquire() {
return new Promise(resolve => {
if (!this._locked) {
this._locked = true;
resolve();
} else {
this._queue.push(resolve);
}
});
}
release() {
if (this._queue.length > 0) {
const nextResolve = this._queue.shift();
nextResolve();
} else {
this._locked = false;
}
}
}
// 使用示例
const lock = new Lock();
async function criticalSection() {
await lock.acquire();
try {
// 临界区代码
} finally {
lock.release();
}
}
使用Async/Await与标志位
通过标志位和循环等待实现简单锁:
let locked = false;
async function withLock(fn) {
while (locked) {
await new Promise(resolve => setTimeout(resolve, 10));
}
locked = true;
try {
return await fn();
} finally {
locked = false;
}
}
// 使用示例
await withLock(async () => {
// 临界区代码
});
使用Atomics实现低级锁(SharedArrayBuffer环境)
在Web Worker共享内存场景下,可使用Atomics API:
const lockBuffer = new SharedArrayBuffer(4);
const lockView = new Int32Array(lockBuffer);
async function acquireLock() {
while (Atomics.wait(lockView, 0, 1) !== 'ok') {
// 等待锁释放
}
Atomics.store(lockView, 0, 1); // 获取锁
}
function releaseLock() {
Atomics.store(lockView, 0, 0);
Atomics.notify(lockView, 0, 1); // 通知等待线程
}
注意事项
- 浏览器环境中优先使用Promise或Async/Await方案
- Node.js可通过
async-mutex等库直接实现 - 避免死锁:确保锁最终被释放,使用try-finally块
- 考虑锁粒度:过细影响性能,过粗降低并发性
第三方库推荐
-
async-mutex:支持互斥锁和信号量npm install async-mutexconst { Mutex } = require('async-mutex'); const mutex = new Mutex(); async function run() { const release = await mutex.acquire(); try { // 临界区 } finally { release(); } } -
proper-lockfile:适用于文件操作场景 -
redis-lock:分布式环境下的Redis锁实现







