Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить SharedArrayBuffer?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`SharedArrayBuffer`** - це спеціальний тип буфера із сирими двійковими даними, який можна розділити між кількома потоками (наприклад, Web Worker і основним потоком) без копіювання даних. **Ключове:** оскільки кілька потоків можуть одночасно читати й писати в одну й ту саму пам'ять, для безпечної синхронізації потрібен об'єкт `Atomics`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке `SharedArrayBuffer` `SharedArrayBuffer` - це спеціальний тип буфера, який: - містить **сирі двійкові дані (байти)**; - може бути **розділений** між різними потоками (наприклад, Web Worker і основним потоком); - дозволяє **одночасно читати й писати** в ту саму пам'ять; - **не копіює** дані при передачі - передається *посилання* на ту саму ділянку пам'яті. ## Відмінність від звичайного `ArrayBuffer` | Властивість | `ArrayBuffer` | `SharedArrayBuffer` | | --- | --- | --- | | Використовується ким | Одним потоком | Кількома потоками | | При передачі воркеру | Копіюється або передається через `transfer` (стає недоступним у вихідному потоці) | Розділяється - обидва потоки бачать ту саму пам'ять | | Можна використовувати Atomics | Ні | Так (для безпечної синхронізації) | | Потокобезпека | Не потрібна | Потрібна (через `Atomics`) | ## Приклад: спільний буфер між потоками ### 1. Основний потік (main.js) ```javascript // Створюємо спільний буфер на 4 байти (Int32 = 4 байти) const sharedBuffer = new SharedArrayBuffer(4); // Обгортаємо його в типізований масив const sharedArray = new Int32Array(sharedBuffer); sharedArray[0] = 0; // початкове значення // Створюємо воркер і передаємо спільний буфер const worker = new Worker('worker.js'); worker.postMessage(sharedBuffer); // Очікуємо змін setInterval(() => { console.log('Main thread value:', sharedArray[0]); }, 1000); ``` ### 2. Воркер (worker.js) ```javascript onmessage = (e) => { const sharedArray = new Int32Array(e.data); // Збільшуємо значення кожні 500 мс setInterval(() => { Atomics.add(sharedArray, 0, 1); // атомарне приростання }, 500); }; ``` Результат: ```javascript Main thread value: 0 Main thread value: 2 Main thread value: 4 Main thread value: 6 ... ``` `SharedArrayBuffer` забезпечує **спільну пам'ять**, а `Atomics` гарантує **потокобезпеку** (без гонок даних). ## Навіщо потрібен `Atomics` Оскільки кілька потоків можуть одночасно читати й записувати одну й ту саму комірку пам'яті, без синхронізації можуть виникати **гонки (race conditions)**. Для цього існує об'єкт `Atomics`, який надає атомарні операції: | Метод | Що робить | | --- | --- | | `Atomics.add(typedArray, index, value)` | Додає значення атомарно | | `Atomics.sub()` | Віднімає атомарно | | `Atomics.and()` / `or()` / `xor()` | Побітові атомарні операції | | `Atomics.load()` / `Atomics.store()` | Безпечне читання/запис | | `Atomics.exchange()` | Змінює значення і повертає старе | | `Atomics.compareExchange()` | Змінює, якщо поточне збігається з очікуваним | | `Atomics.wait()` / `Atomics.notify()` | Дозволяє "приспати" потік, поки значення не зміниться (лише у воркерах) | ## Приклад: синхронізація за допомогою `Atomics.wait` / `Atomics.notify` ```javascript // main.js const sharedBuffer = new SharedArrayBuffer(4); const sharedArray = new Int32Array(sharedBuffer); const worker = new Worker('worker.js'); worker.postMessage(sharedBuffer); // Через 2 секунди "розбудимо" воркер setTimeout(() => { console.log('Main: notify worker'); Atomics.store(sharedArray, 0, 1); Atomics.notify(sharedArray, 0, 1); }, 2000); ``` ```javascript // worker.js onmessage = (e) => { const sharedArray = new Int32Array(e.data); console.log('Worker: waiting...'); Atomics.wait(sharedArray, 0, 0); // чекає, поки значення не зміниться console.log('Worker: woken up, value:', sharedArray[0]); }; ``` Тут воркер буквально "спить", поки основний потік не "розбудить" його. Це дає **реальну багатопотоковість** (координацію між потоками JS). ## Де використовується `SharedArrayBuffer` | Сценарій | Застосування | | --- | --- | | **Web Workers** | Передача великих даних без копіювання | | **Багатопотокові обчислення** | Паралельна обробка матриць, графіки, фізики | | **Ігри та симуляції** | Оновлення стану світу в кількох потоках | | **Machine Learning / WASM** | TensorFlow.js, WebAssembly, OpenCV використовують `SharedArrayBuffer` | | **Обробка відео / аудіо** | Спільне використання буферів між потоками | | **Шина обміну між воркерами** | Миттєва передача даних без серіалізації JSON | ## Безпека й обмеження (CORS / COOP / COEP) Через ризики **вразливостей Spectre** браузери вмикають `SharedArrayBuffer` **лише в ізольованих контекстах** (Cross-Origin Isolation). Щоб `SharedArrayBuffer` працював у браузері, потрібно виставити правильні заголовки: ```javascript Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` І переконатися, що всі ресурси (скрипти, воркери) також сумісні з цим режимом. ## Приклад: увімкнення Cross-Origin Isolation Для dev-сервера (наприклад, Vite чи Express): ```javascript app.use((req, res, next) => { res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); next(); }); ``` Тепер браузер дозволить використовувати `SharedArrayBuffer`. ## Підсумок | Властивість | Опис | | --- | --- | | Що робить | Розділяє пам'ять між потоками без копіювання | | Де працює | У Web Workers і Node.js (worker_threads) | | Вимагає | `Atomics` для синхронізації | | Безпека | Лише при увімкненому COOP/COEP | | Типові сценарії | Паралельні обчислення, кеш, рендеринг, WebAssembly | | Аналог у C/C++ | Спільна пам'ять (`shared memory`) між потоками | **Головна ідея:** > `SharedArrayBuffer` дає JavaScript можливість *реального паралелізму* > - кілька потоків можуть читати й писати **в одну пам'ять одночасно**, > а `Atomics` при цьому забезпечує **коректність і синхронізацію**.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.