MST
星途 面试题库

面试题:JavaScript数组读写并发与错误处理机制设计

考虑一个多线程(或使用Web Workers模拟多线程环境)的JavaScript应用场景,多个线程同时对同一个数组进行读写操作。请设计一套错误处理机制,能够在发生读写冲突或数据不一致错误时,及时捕获并处理,保证数组数据的完整性和程序的稳定性,详细描述你的设计思路及关键代码实现。
25.6万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 锁机制:使用互斥锁(Mutex)来确保同一时间只有一个线程能够对数组进行写操作。读操作可以允许多个线程同时进行,但在有写操作时,读操作需要等待写操作完成。
  2. 版本控制:为数组添加版本号,每次写操作增加版本号。读操作时记录当前版本号,如果在读操作过程中版本号发生变化,说明数据被修改,需要重新读取。
  3. 错误捕获:在读写操作的关键位置使用try - catch块来捕获可能出现的错误,如读写冲突或数据不一致错误。

关键代码实现

  1. 使用Web Workers模拟多线程环境
    • 主线程代码(index.js)
// 创建一个新的Web Worker
const worker = new Worker('worker.js');

// 向Worker发送数组数据
const sharedArray = [1, 2, 3, 4];
worker.postMessage({ action: 'init', data: sharedArray });

// 监听来自Worker的消息
worker.onmessage = function (e) {
    if (e.data.error) {
        console.error('Error in worker:', e.data.error);
    } else {
        console.log('Updated array from worker:', e.data.result);
    }
};

// 模拟主线程对数组的写操作
setTimeout(() => {
    worker.postMessage({ action: 'write', data: [5, 6] });
}, 2000);
  • Web Worker代码(worker.js)
let sharedArray;
let version = 0;
let lock = false;

self.onmessage = function (e) {
    try {
        if (e.data.action === 'init') {
            sharedArray = e.data.data;
        } else if (e.data.action ==='read') {
            if (lock) {
                throw new Error('Read conflict: Write operation in progress');
            }
            const currentVersion = version;
            self.postMessage({ result: sharedArray, version: currentVersion });
        } else if (e.data.action === 'write') {
            if (lock) {
                throw new Error('Write conflict: Another write operation in progress');
            }
            lock = true;
            sharedArray = e.data.data;
            version++;
            lock = false;
            self.postMessage({ result: sharedArray, version: version });
        }
    } catch (error) {
        self.postMessage({ error: error.message });
    }
};
  1. 使用JavaScript原生多线程(Node.js的worker_threads模块)
    • 主线程代码(main.js)
const { Worker } = require('worker_threads');

// 创建一个新的Worker
const worker = new Worker('worker.js');

// 向Worker发送数组数据
const sharedArray = [1, 2, 3, 4];
worker.postMessage({ action: 'init', data: sharedArray });

// 监听来自Worker的消息
worker.on('message', function (e) {
    if (e.error) {
        console.error('Error in worker:', e.error);
    } else {
        console.log('Updated array from worker:', e.result);
    }
});

// 模拟主线程对数组的写操作
setTimeout(() => {
    worker.postMessage({ action: 'write', data: [5, 6] });
}, 2000);
  • Worker代码(worker.js)
const { parentPort } = require('worker_threads');

let sharedArray;
let version = 0;
let lock = false;

parentPort.on('message', function (e) {
    try {
        if (e.data.action === 'init') {
            sharedArray = e.data.data;
        } else if (e.data.action ==='read') {
            if (lock) {
                throw new Error('Read conflict: Write operation in progress');
            }
            const currentVersion = version;
            parentPort.postMessage({ result: sharedArray, version: currentVersion });
        } else if (e.data.action === 'write') {
            if (lock) {
                throw new Error('Write conflict: Another write operation in progress');
            }
            lock = true;
            sharedArray = e.data.data;
            version++;
            lock = false;
            parentPort.postMessage({ result: sharedArray, version: version });
        }
    } catch (error) {
        parentPort.postMessage({ error: error.message });
    }
});

以上代码通过锁机制和版本控制,结合错误捕获,在多线程环境下保证了数组数据的完整性和程序的稳定性。不同环境(浏览器Web Workers和Node.js worker_threads)下的实现思路类似,但具体API有所不同。