--- title: SharedArrayBuffer slug: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer translation_of: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer tags: - Класс - JavaScript - Разделяемая память - SharedArrayBuffer - TypedArrays ---
Объект SharedArrayBuffer
подобен ArrayBuffer, то есть это буфер фиксированной длины, использующийся для хранения любых бинарных данных. Главное отличие SharedArrayBuffer
от ArrayBuffer
заключается в том, что он используется для создания разделяемой области памяти. В отличие от ArrayBuffer
SharedArrayBuffer
не может быть откреплён от соответствующей ему области памяти.
Для совместного использования памяти с помощью объекта {{jsxref("SharedArrayBuffer")}} между одним агентом в кластере и другим (агентом может быть как основная программа страницы сайта, так и один из её веб-воркеров) используются postMessage
и алгоритм структурированного клонирования.
Алгоритм структурированного клонирования принимает SharedArrayBuffers
и TypedArrays
, отображённый в SharedArrayBuffers
. В обоих случаях объект SharedArrayBuffer
передаётся получателю, что приводит к появлению нового приватного объекта SharedArrayBuffer внутри агента-получателя (так же как для {{jsxref("ArrayBuffer")}}). Оба объекта SharedArrayBuffer
ссылаются на один и тот же блок общих данных, и побочный эффект, изменяющий блок данных в одном из агентов, в итоге проявится в другом агенте.
var sab = new SharedArrayBuffer(1024); worker.postMessage(sab);
Разделяемую память можно создавать и изменять одновременно в воркерах или основном потоке. В зависимости от системы (ЦПУ, ОС, браузера), распространение изменений по всем контекстам может занять некоторое время. Для синхронизации необходимы {{jsxref("Атомарные", "атомарные", "", 1)}} операции .
SharedArrayBuffer
WebGLRenderingContext.bufferData()
WebGLRenderingContext.bufferSubData()
WebGL2RenderingContext.getBufferSubData()
Разделяемая память и таймеры высокого разрешения были отключены в начале 2018 года из-за атаки Spectre. В 2020 году был стандартизирован новый, безопасный подход, чтобы включить разделяемую память обратно. При следовании следующим мерам безопасности postMessage() не будет выкидывать исключение для
SharedArrayBuffer
, и разделяемая память будет доступна в разных потоках.
Основное требование — ваш документ должен находиться в безопасном контексте
Для документов верхнего уровня нужно устновить два заголовка, чтобы изолировать ваш сайт от других источников (cross-origin):
Cross-Origin-Opener-Policy
со значением same-origin
(защищает ваш источник от атаки)Cross-Origin-Embedder-Policy
со значением require-corp
(защищает жертв от вашего источника)Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp
Чтобы проверить, что изоляция от других источников прошла успешно, протестируйте свойство crossOriginIsolated
, доступное для контекстов окна и воркера:
if (crossOriginIsolated) { // Начни работу с SharedArrayBuffer } else { // Сделай что-то другое }
Ознакомьтесь с планируемыми изменениями разделяемой памяти, которые начинают внедряться в браузерах (например, в Firefox 79).
Конструкторы SharedArrayBuffer
необходимо вызывать с помощью оператора {{jsxref("Operators/new", "new")}}. Вызов конструктора SharedArrayBuffer
как функции без указания new
вызовет ошибку {{jsxref("TypeError")}}.
var sab = SharedArrayBuffer(1024); // TypeError: вызов встроенного конструктора SharedArrayBuffer // без new запрещено
var sab = new SharedArrayBuffer(1024);
SharedArrayBuffer()
SharedArrayBuffer
.SharedArrayBuffer
, чьё содержимое — копия байтов изначального SharedArrayBuffer
с begin
(начала) включительно до end
(конца), но не включая его. Если параметры begin
или end
отрицательны, метод обращается к индексу массива, начиная с конца, а не с начала.var sab = new SharedArrayBuffer(1024);
sab.slice(); // SharedArrayBuffer { byteLength: 1024 } sab.slice(2); // SharedArrayBuffer { byteLength: 1022 } sab.slice(-2); // SharedArrayBuffer { byteLength: 2 } sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }
const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);
Спецификация |
---|
{{SpecName('ESDraft', '#sec-sharedarraybuffer-objects', 'SharedArrayBuffer')}} |
{{Compat("javascript.builtins.SharedArrayBuffer")}}
Немного о новых примитивах JavaScript для параллелизации работ – Mozilla Hacks