MST

星途 面试题库

面试题:JavaScript 函数作为命名空间下并发管理中的资源竞争问题及解决方案

在JavaScript中,使用函数作为命名空间来管理并发任务时,可能会遇到资源竞争的情况。请描述一个可能出现资源竞争的场景,并给出至少两种有效的解决方案。同时用代码示例展示如何通过这些方案解决资源竞争问题。
29.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

可能出现资源竞争的场景

假设有一个函数 count 用于对共享变量 counter 进行计数操作,多个并发任务都调用这个函数时,由于JavaScript单线程但异步的特性,可能会出现资源竞争。例如:

let counter = 0;
function count() {
    counter++;
    return counter;
}

function task() {
    for (let i = 0; i < 1000; i++) {
        count();
    }
}

// 模拟多个并发任务
const tasks = Array.from({ length: 10 }, () => task());
Promise.all(tasks).then(() => {
    console.log('Final counter value should be 10000, but might be less:', counter);
});

在上述代码中,理论上10个任务,每个任务循环1000次,counter 最终应该是10000,但由于资源竞争,实际值可能小于10000。

解决方案及代码示例

  1. 使用 async/await 结合 Promise 顺序执行 通过将任务顺序执行,避免同时访问共享资源。
let counter = 0;
function count() {
    counter++;
    return counter;
}

async function task() {
    for (let i = 0; i < 1000; i++) {
        count();
    }
}

async function executeTasksSequentially() {
    const tasks = Array.from({ length: 10 }, () => task());
    for (const task of tasks) {
        await task();
    }
    console.log('Final counter value:', counter);
}

executeTasksSequentially();
  1. 使用 Mutex(互斥锁)模拟 通过一个标志位来表示资源是否被占用,从而控制对共享资源的访问。
let counter = 0;
let isLocked = false;
function count() {
    while (isLocked);
    isLocked = true;
    counter++;
    isLocked = false;
    return counter;
}

function task() {
    for (let i = 0; i < 1000; i++) {
        count();
    }
}

const tasks = Array.from({ length: 10 }, () => task());
Promise.all(tasks).then(() => {
    console.log('Final counter value:', counter);
});
  1. 使用 Atomics 对象(适用于共享内存环境,如Web Workers) Atomics 提供了原子操作,能有效避免资源竞争。
// 假设在Web Worker环境
const sharedArrayBuffer = new SharedArrayBuffer(4);
const int32Array = new Int32Array(sharedArrayBuffer);
int32Array[0] = 0;

function count() {
    return Atomics.add(int32Array, 0, 1);
}

function task() {
    for (let i = 0; i < 1000; i++) {
        count();
    }
}

const tasks = Array.from({ length: 10 }, () => task());
Promise.all(tasks).then(() => {
    console.log('Final counter value:', int32Array[0]);
});