Java Synchronized块在Node.js中的等价实现 限制方法仅单Promise执行
Node.js 异步方法互斥锁实现方案
核心思路
你的问题核心是异步方法的执行竞态:虽然Node.js是单线程运行,但await关键字会让出事件循环,导致校验和插入的间隙可以响应其他方法调用,进而触发数据一致性问题。我们只需要给目标方法加执行锁,保证同一时间只有一个调用能走完「数据库校验+插入」的完整流程即可。
代码实现
class YourService { // 私有锁标记:标记当前方法是否正在运行 #isMyMethodLocked = false; // 等待队列:存储后续并发调用的待执行任务 #myMethodQueue: Array<() => void> = []; async myMethod(obj: MyObj): Promise<MyObj> { // 已有任务在运行,将当前调用加入等待队列 if (this.#isMyMethodLocked) { return new Promise((resolve, reject) => { this.#myMethodQueue.push(async () => { try { const result = await this.#runMyMethodLogic(obj); resolve(result); } catch (err) { reject(err); } }); }); } // 无运行任务,直接上锁执行 this.#isMyMethodLocked = true; try { return await this.#runMyMethodLogic(obj); } finally { // 当前任务执行完成,解锁并处理队列中下一个任务 this.#isMyMethodLocked = false; const nextTask = this.#myMethodQueue.shift(); nextTask?.(); } } // 抽离原方法的核心业务逻辑 async #runMyMethodLogic(obj: MyObj): Promise<MyObj> { const canInsert = await this.DbChecks(); if (canInsert === true) { return this.insert(obj); } // 补充原逻辑缺失的分支返回,可根据业务需求调整为返回null或自定义错误 throw new Error('当前不允许执行插入操作'); } }
方案说明
- 完全保证核心逻辑同一时间只有一个实例在运行,彻底避免校验和插入的间隙被其他调用修改数据库的问题
- 并发调用会按触发顺序进入队列排队,前一个调用执行完成(无论成功失败)后才会执行下一个
- 如果业务不需要排队等待,而是要直接拒绝并发调用,可以简化逻辑:检测到锁被占用时直接抛出「并发调用受限」的错误即可
可选优化
如果互斥不需要全局生效,只需要针对特定维度(比如同一个用户、同一条数据ID)生效,可以把锁改成Map结构,key为对应维度的标识,能有效缩小锁粒度、提升并发性能。
内容的提问来源于stack exchange,提问作者Litel
相关产品推荐
相关产品推荐

