SharedArrayBuffer
позволяет нескольким потокам работать с общей областью памяти, что приводит к классическим проблемам параллелизма:
Специальный API для атомарных операций:
const { Worker, isMainThread, SharedArrayBuffer } = require('worker_threads');
if (isMainThread) {
const sab = new SharedArrayBuffer(1024);
const arr = new Int32Array(sab);
// Инициализация защищенного значения
Atomics.store(arr, 0, 0);
new Worker(__filename, { workerData: sab });
} else {
const arr = new Int32Array(workerData);
// Атомарное увеличение значения
Atomics.add(arr, 0, 1);
}
Реализация взаимного исключения на основе Atomics:
class Mutex {
constructor(sharedArray, index) {
this.lock = new Int32Array(sharedArray);
this.index = index;
}
acquire() {
while (true) {
if (Atomics.compareExchange(this.lock, this.index, 0, 1) === 0) {
return;
}
Atomics.wait(this.lock, this.index, 1);
}
}
release() {
if (Atomics.compareExchange(this.lock, this.index, 1, 0) !== 1) {
throw new Error('Mutex is not acquired');
}
Atomics.notify(this.lock, this.index, 1);
}
}
Контроль доступа для ограниченного числа потоков:
class Semaphore {
constructor(sharedArray, index, initial) {
this.array = new Int32Array(sharedArray);
this.index = index;
Atomics.store(this.array, this.index, initial);
}
acquire() {
while (true) {
const current = Atomics.load(this.array, this.index);
if (current > 0 &&
Atomics.compareExchange(this.array, this.index, current, current - 1) === current) {
return;
}
Atomics.wait(this.array, this.index, 0);
}
}
release() {
const current = Atomics.add(this.array, this.index, 1);
Atomics.notify(this.array, this.index, 1);
}
}
// Главный поток
const sab = new SharedArrayBuffer(4);
const counter = new Int32Array(sab);
Atomics.store(counter, 0, 0);
// Воркер
Atomics.add(counter, 0, 1); // Атомарное увеличение
// Безопасная запись
Atomics.store(array, index, newValue);
// Безопасное чтение
const value = Atomics.load(array, index);
Прямые операции без синхронизации:
// ОПАСНО! Возможна потеря данных
sharedArray[0] += 1;
Неиспользование Atomics для координации:
// Ненадежно
if (sharedArray[0] === 1) {
// Условие может устареть к моменту выполнения
}
Правильная работа с SharedArrayBuffer требует дисциплины и понимания многопоточного программирования. Всегда тестируйте такие участки кода под нагрузкой!