如何避免此类竞态条件(race condition)?API并发调用下单实例任务处理
关于“Big Baby”实例的并发串行化处理方案
嘿,先明确一点:这个场景严格来说不算典型的竞态条件,但确实是并发场景下的资源独占问题——你需要保证同一时间只有一个操作在“big baby”实例上执行,其他请求排队等待,对吧?
竞态条件通常是指多个操作同时读写共享状态,导致最终结果依赖于执行顺序的不可预测性;而你的需求是强制串行化执行所有对“big baby”的操作,避免并发调用带来的问题,这个我们可以通过一个简单的队列机制来实现。
下面是一个可落地的实现思路(以JavaScript/Node.js为例,毕竟是API场景常用环境):
class BigBabyTaskQueue { constructor(bigBabyInstance) { this.bigBaby = bigBabyInstance; // 用一个Promise跟踪当前正在执行的任务,初始为已完成状态 this.currentExecutingTask = Promise.resolve(); } // 对外暴露的执行方法,接收一个操作函数(参数是bigBaby实例),返回Promise enqueueOperation(operation) { return new Promise((resolve, reject) => { // 将新操作链式绑定到当前任务之后,确保串行执行 this.currentExecutingTask = this.currentExecutingTask .then(() => operation(this.bigBaby)) .then(result => resolve(result)) .catch(error => reject(error)); }); } } // ------------------------------ // 使用示例 // ------------------------------ // 模拟你的"big baby"实例,只能同时处理一个操作 const myBigBaby = { performAction(input) { // 模拟耗时操作,比如调用硬件、执行独占性计算等 return new Promise((resolve) => { setTimeout(() => { resolve(`操作完成:输入内容「${input}」`); }, 1000); }); } }; // 初始化队列 const taskQueue = new BigBabyTaskQueue(myBigBaby); // 模拟并发API调用场景 async function simulateConcurrentApiCalls() { // 同时发起3个请求 const requestPromises = [ taskQueue.enqueueOperation(baby => baby.performAction("API请求1")), taskQueue.enqueueOperation(baby => baby.performAction("API请求2")), taskQueue.enqueueOperation(baby => baby.performAction("API请求3")) ]; // 等待所有请求完成 const results = await Promise.all(requestPromises); console.log(results); // 输出顺序会严格是: // ["操作完成:输入内容「API请求1」", "操作完成:输入内容「API请求2」", "操作完成:输入内容「API请求3」"] } simulateConcurrentApiCalls();
方案说明:
currentExecutingTask作为任务链的锚点,始终指向当前正在执行(或等待执行)的最后一个任务Promise。- 每次调用
enqueueOperation时,都会把新的操作追加到任务链末尾,确保前一个操作完全完成后才会启动下一个。 - 每个API调用都会得到一个专属的Promise,当对应的操作在队列中执行完成后,这个Promise会自动resolve操作结果,完美匹配你的需求。
如果你的“big baby”操作是同步的(而非异步Promise),只需要稍微修改enqueueOperation里的逻辑,把同步操作包装成Promise即可,核心的队列机制是一样的。
内容的提问来源于stack exchange,提问作者Fabian Mendez




