1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 10:22:23 +00:00

docs(arrayBuffer): edit sharedBuffer

This commit is contained in:
ruanyf 2017-06-28 10:30:37 +08:00
parent 24b53305d4
commit 17d24e69a7
2 changed files with 100 additions and 21 deletions

View File

@ -975,6 +975,8 @@ bitmap.pixels = new Uint8Array(buffer, start);
## SharedArrayBuffer
### 共享内存
JavaScript 是单线程的Web worker 引入了多线程主线程用来与用户互动Worker 线程用来承担计算任务。每个线程的数据都是隔离的,通过`postMessage()`通信。下面是一个例子。
```javascript
@ -1029,7 +1031,13 @@ Worker 线程从事件的`data`属性上面取到数据。
// Worker 线程
var sharedBuffer;
onmessage = function (ev) {
sharedBuffer = ev.data; // 1KB 的共享内存,就是主线程共享出来的那块内存
// 主线程共享的数据,就是 1KB 的共享内存
const sharedBuffer = ev.data;
// 在共享内存上建立视图,方便读写
const sharedArray = new Int32Array(sharedBuffer);
// ...
};
```
@ -1067,6 +1075,8 @@ onmessage = function (ev) {
};
```
### Atomics 对象
多线程共享内存最大的问题就是如何防止两个线程同时修改某个地址或者说当一个线程修改共享内存以后必须有一个机制让其他线程同步。SharedArrayBuffer API 提供`Atomics`对象,保证所有共享内存的操作都是“原子性”的,并且可以在所有进程内同步。
```javascript
@ -1085,7 +1095,90 @@ Atomics.add(ia, 112, 1); // 正确
上面代码中Worker 线程直接改写共享内存是不正确的。有两个原因,一是可能发生两个线程同时改写该地址,二是改写以后无法同步到其他 Worker 线程。所以,必须使用`Atomics.add()`方法进行改写。
下面是另一个例子。
`Atomics`提供多种方法。
**1Atomics.store()Atomics.load()**
`store()`方法用来向共享内存写入数据,`load()`方法用来从共享内存读出数据。比起直接的读写操作,它们的好处是保证了读写操作的安全性。比如有时编译器为了优化,会改变某些操作的执行顺序,从而导致其他线程读取时出现问题,`store``load`就保证了编辑器不会改变这些操作。
```javascript
Atomics.load(array, index)
Atomics.store(array, index, value)
```
`store`方法接受三个参数SharedBuffer 的视图、位置索引和值,返回`sharedA[index]`的值。`load`方法只接受两个参数SharedBuffer 的视图和位置索引,也是返回`sharedArray[index]`的值。
```javascript
// 主线程 main.js
console.log('notifying...');
Atomics.store(sharedArray, 0, 123);
// Worker 线程 worker.js
while (Atomics.load(sharedArray, 0) !== 123) ;
console.log('notified');
```
上面代码中,主线程的`Atomics.store`向 SharedBuffer 视图的0号位置写入123。Worker 线程的`Atomics.load`从该位置读出数据只要不等于123就不断循环。
**2Atomics.wait()Atomics.wake()**
使用`while`循环等待主线程的通知,不是很高效,`Atomics`对象提供了`wait()``wake()`两个方法用于等待通知。
```javascript
Atomics.wait(sharedArray, index, value, time)
```
`Atomics.wait`用于当`sharedArray[index]`不等于`value`,就返回`not-equal`,否则就进入休眠,只有使用`Atomics.wake()`或者`time`毫秒以后才能唤醒。被`Atomics.wake()`唤醒时,返回`ok`,超时唤醒时返回`timed-out`
```javascript
Atomics.wake(sharedArray, index, count)
```
`Atomics.wake`用于唤醒`count`数目在`sharedArray[index]`位置休眠的线程,让它继续往下运行。
**3运算方法**
共享内存上面的某些运算是不能被打断的即不能在运算过程中让其他线程改写内存上面的值。Atomics 对象提供了一些运算方法,防止数据被改写。
```javascript
Atomics.add(sharedArray, index, value)
```
`Atomics.add`用于将`value`加到`sharedArray[index]`,返回`sharedArray[index]`旧的值。
```javascript
Atomics.sub(sharedArray, index, value)
```
`Atomics.sub`用于将`value``sharedArray[index]`减去,返回`sharedArray[index]`旧的值。
```javascript
Atomics.and(sharedArray, index, value)
```
`Atomics.and`用于将`value``sharedArray[index]`进行位运算`and`,放入`sharedArray[index]`,并返回旧的值。
```javascript
Atomics.or(sharedArray, index, value)
```
`Atomics.or`用于将`value``sharedArray[index]`进行位运算`or`,放入`sharedArray[index]`,并返回旧的值。
```javascript
Atomics.xor(sharedArray, index, value)
```
`Atomic.xor`用于将`vaule``sharedArray[index]`进行位运算`xor`,放入`sharedArray[index]`,并返回旧的值。
**4其他方法**
`Atomics`对象还有以下方法。
- `Atomics.compareExchange(sharedArray, index, oldval, newval)`:如果`sharedArray[index]`等于`oldval`,就写入`newval`,返回`oldval`
- `Atomics.exchange(sharedArray, index, value)`:设置`sharedArray[index]`的值,返回旧的值。
- `Atomics.isLockFree(size)`:返回一个布尔值,表示`Atomics`对象是否可以处理某个`size`的内存锁定。如果返回`false`,应用程序就需要自己来实现锁定。
### Atomics 对象的例子
```javascript
// 线程一
@ -1098,20 +1191,5 @@ Atomics.wait(ia, 37, 163);
console.log(ia[37]); // 123456
```
上面代码中,共享内存`ia`的第37号位置原来的值是`163`。进程二使用`Atomics.wait()`方法,指定只要`ia[37]`等于`163`,就处于“等待”状态。进程一使用`Atomics.store()`方法,将`123456`放入`ia[37]`,然后使用`Atomics.wake()`方法将监视`ia[37]`的一个线程唤醒。
`Atomics`对象有以下方法。
- `Atomics.load(array, index)`:返回`array[index]`的值。
- `Atomics.store(array, index, value)`:设置`array[index]`的值,返回这个值。
- `Atomics.compareExchange(array, index, oldval, newval)`:如果`array[index]`等于`oldval`,就写入`newval`,返回`oldval`
- `Atomics.exchange(array, index, value)`:设置`array[index]`的值,返回旧的值。
- `Atomics.add(array, index, value)`:将`value`加到`array[index]`,返回`array[index]`旧的值。
- `Atomics.sub(array, index, value)`:将`value``array[index]`减去,返回`array[index]`旧的值。
- `Atomics.and(array, index, value)`:将`value``array[index]`进行位运算`and`,放入`array[index]`,并返回旧的值。
- `Atomics.or(array, index, value)`:将`value``array[index]`进行位运算`or`,放入`array[index]`,并返回旧的值。
- `Atomics.xor(array, index, value)`:将`vaule``array[index]`进行位运算`xor`,放入`array[index]`,并返回旧的值。
- `Atomics.wait(array, index, value, timeout)`:如果`array[index]`等于`value`,进程就进入休眠状态,必须通过`Atomics.wake()`唤醒。`timeout`指定多少毫秒之后进入休眠。返回值是三个字符串ok、not-equal、timed-out中的一个。
- `Atomics.wake(array, index, count)`:唤醒指定数目在某个位置休眠的进程。
- `Atomics.isLockFree(size)`:返回一个布尔值,表示`Atomics`对象是否可以处理某个`size`的内存锁定。如果返回`false`,应用程序就需要自己来实现锁定。
上面代码中,共享内存视图`ia`的第37号位置原来的值是`163`。进程二使用`Atomics.wait()`方法,指定只要`ia[37]`等于`163`,就进入休眠状态。进程一使用`Atomics.store()`方法,将`123456`放入`ia[37]`,然后使用`Atomics.wake()`方法将监视`ia[37]`的一个休眠线程唤醒。

View File

@ -220,6 +220,7 @@
- Ian Elliot, [Reading A BMP File In JavaScript](http://www.i-programmer.info/projects/36-web/6234-reading-a-bmp-file-in-javascript.html)
- Renato Mangini, [How to convert ArrayBuffer to and from String](http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String)
- Axel Rauschmayer, [Typed Arrays in ECMAScript 6](http://www.2ality.com/2015/09/typed-arrays.html)
- Axel Rauschmayer, [ES proposal: Shared memory and atomics](http://2ality.com/2017/01/shared-array-buffer.html)
## SIMD
@ -239,7 +240,7 @@
- army8735, [Javascript Downcast](https://github.com/army8735/jsdc): 国产的ES6到ES5的转码器
- esnext, [ES6 Module Transpiler](https://github.com/esnext/es6-module-transpiler)基于node.js的将ES6模块转为ES5代码的命令行工具
- Sebastian McKenzie, [BabelJS](http://babeljs.io/): ES6转译器
- SystemJS, [SystemJS](https://github.com/systemjs/systemjs): 在浏览器中加载AMD、CJS、ES6模块的一个垫片库
- Modernizr, [HTML5 Cross Browser Polyfills](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#ecmascript-6-harmony): ES6垫片库清单
- Facebook, [regenerator](https://github.com/facebook/regenerator): 将Generator函数转为ES5的转码器
- SystemJS, [SystemJS](https://github.com/systemjs/systemjs): 在浏览器中加载 AMD、CJS、ES6 模块的一个垫片库
- Modernizr, [HTML5 Cross Browser Polyfills](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#ecmascript-6-harmony): ES6 垫片库清单
- Facebook, [regenerator](https://github.com/facebook/regenerator): 将 Generator 函数转为 ES5 的转码器