面试题答案
一键面试可能出现资源竞争的场景
假设有一个函数 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。
解决方案及代码示例
- 使用
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();
- 使用
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);
});
- 使用
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]);
});