You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何避免此类竞态条件(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

火山引擎 最新活动