MST

星途 面试题库

面试题:JavaScript 数组并发添加删除中的竞争条件处理

在一个有多个并发操作(添加和删除元素)的 JavaScript 数组场景中,可能会出现竞争条件导致数据不一致。请编写一个函数,使用 `Promise` 或者 `async/await` 来处理这些并发操作,确保每次添加或删除操作都能正确执行,且不会出现数据丢失或错误的情况。同时,阐述你对如何防止竞争条件的理解。
18.1万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

代码实现

let dataArray = [];

async function performOperation(operation, value) {
    return new Promise((resolve, reject) => {
        if (operation === 'add') {
            dataArray.push(value);
            resolve(dataArray);
        } else if (operation === 'delete') {
            const index = dataArray.indexOf(value);
            if (index > -1) {
                dataArray.splice(index, 1);
                resolve(dataArray);
            } else {
                reject(new Error('Element not found for deletion'));
            }
        } else {
            reject(new Error('Invalid operation'));
        }
    });
}

// 示例用法
performOperation('add', 1)
   .then(result => console.log(result))
   .catch(error => console.error(error));

performOperation('delete', 1)
   .then(result => console.log(result))
   .catch(error => console.error(error));

对防止竞争条件的理解

  1. 竞争条件:在并发编程中,竞争条件是指多个线程或进程在访问共享资源时,由于执行顺序的不确定性而导致程序出现不可预期的结果。在 JavaScript 数组的并发添加和删除操作场景中,可能会出现一个操作还未完成,另一个操作就开始执行,导致数据不一致,比如删除了未完全添加的元素,或者添加操作覆盖了本应删除的元素等。
  2. 防止竞争条件的方法
    • 使用队列或顺序执行:在上述代码中,通过 Promiseasync/await 将操作顺序化。每次操作都返回一个 Promise,并且只有前一个操作完成(resolvereject)后,下一个操作才会开始,这样就避免了多个操作同时修改数组导致的数据不一致。
    • 加锁机制:虽然 JavaScript 是单线程语言,但在 Node.js 环境下处理多进程或浏览器环境下使用 Web Workers 时,可以引入类似加锁的概念。比如使用一个标志变量表示当前是否有操作正在进行,只有当标志为空闲时,新的操作才能开始,操作完成后再释放标志。
    • 使用不可变数据结构:在一些场景下,可以使用不可变数据结构,每次操作返回一个新的数据结构而不是直接修改原有的数据。这样可以避免多个操作直接修改同一数据带来的竞争问题,但这种方法可能在某些情况下性能开销较大,需要根据具体场景权衡。