Node.js工作线程共享对象/存储

Node.js工作线程共享对象/存储,node.js,multithreading,worker-thread,Node.js,Multithreading,Worker Thread,所以,我在读一些关于Node.js的资料,当我看到这些资料时,我很惊讶 在我看来,拥有线程是一个很好的优势,特别是如果你把它与共享内存访问结合起来的话。正如您可能已经想到的->SharedArrayBuffer 是的,我就是这么想的。因此,我想到的第一件事是对它进行一个小测试,并尝试实现一个简单的存储(现在是一个简单的对象),它将在线程之间共享 问题是,(除非我这里遗漏了什么),如何使用SharedArrayBuffer,从n个线程访问对象 我知道,对于一个简单的uint32阵列来说是可行的,但

所以,我在读一些关于Node.js的资料,当我看到这些资料时,我很惊讶

在我看来,拥有线程是一个很好的优势,特别是如果你把它与共享内存访问结合起来的话。正如您可能已经想到的->
SharedArrayBuffer

是的,我就是这么想的。因此,我想到的第一件事是对它进行一个小测试,并尝试实现一个简单的
存储
(现在是一个简单的对象),它将在线程之间共享

问题是,(除非我这里遗漏了什么),如何使用
SharedArrayBuffer
,从n个线程访问对象

我知道,对于一个简单的
uint32阵列来说
是可行的,但是对于这个对象,可以做什么呢

一开始我想把它转换成
uint32数组,就像你在下面看到的那样,但即使是看那该死的源代码也让我想哭

const {
    Worker,
    isMainThread,
    workerData
} = require('worker_threads');

const store = {
    ks109: {
        title: 'some title 1',
        description: 'some desciption 1',
        keywords: ['one', 'two']
    },
    ks110: {
        title: 'some title 2',
        description: 'some desciption 2',
        keywords: ['three', 'four']
    },
    ks111: {
        title: 'some title 3',
        description: 'some desciption 3',
        keywords: ['five', 'six']
    }
}

const shareObject = (obj) => {

    let OString = JSON.stringify(obj);
    let SABuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * OString.length);
    let sArray = new Int32Array(SABuffer);

    for (let i = 0; i < OString.length; i++) {
        sArray[i] = OString.charCodeAt(i);
    }

    return sArray;

}

if (isMainThread) {

    const sharedStore = shareObject(store);

    console.log('[Main][Data Before]:', sharedStore.slice(-10));

    let w = new Worker(__filename, {
        workerData: sharedStore
    });

    w.on('message', (msg) => {
        console.log(`[Main][Thread message]: ${msg}`);
    });
    w.on('error', (err) => {
        console.error(`[Main][Thread error] ${err.message}`);
    });
    w.on('exit', (code) => {
        if (code !== 0) {
            console.error(`[Main][Thread unexpected exit]: ${code}`);
        }
    });

    setInterval(() => {
        // At some point you ll see a value change,
        // it's 'six' becoming 'sax' (big time!) 
        console.log('[Main][Data Check]:', sharedStore.slice(-10));
    }, 1000);

} else {

    let str = String.fromCharCode.apply(this, workerData);
    let obj = JSON.parse(str);

    obj.ks111.keywords[1] = 'sax'; // big time!

    let OString = JSON.stringify(obj);

    for (let i = 0; i < OString.length; i++) {
        workerData[i] = OString.charCodeAt(i);
    }

}
const{
工人
伊斯曼特莱德,
工作数据
}=需要('worker_threads');
常数存储={
ks109:{
标题:“一些标题1”,
描述:“一些描述1”,
关键词:[‘一’、‘二’]
},
ks110:{
标题:“一些标题2”,
描述:“一些描述2”,
关键词:[‘三’、‘四’]
},
ks111:{
标题:“一些标题3”,
描述:“一些描述3”,
关键词:[‘五’、‘六’]
}
}
常量shareObject=(obj)=>{
让OString=JSON.stringify(obj);
设SABuffer=new-SharedArrayBuffer(Int32Array.BYTES\u/u元素*OString.length);
设sArray=newint32array(SABuffer);
for(设i=0;i{
log(`[Main][threadmessage]:${msg}`);
});
w、 on('error',(err)=>{
错误(`[Main][threaderror]${err.message}`);
});
w、 on('退出',(代码)=>{
如果(代码!==0){
错误(`[Main][线程意外退出]:${code}`);
}
});
设置间隔(()=>{
//在某个时刻,您会看到值发生变化,
//现在是“六”变成“萨克斯”(重要时刻!)
console.log('[Main][数据检查]:',sharedStore.slice(-10));
}, 1000);
}否则{
让str=String.fromCharCode.apply(这是workerData);
让obj=JSON.parse(str);
obj.ks111.keywords[1]=“sax”;//太棒了!
让OString=JSON.stringify(obj);
for(设i=0;i

总之,Node.js 10.5.0中线程之间的共享对象,可能吗?如何执行?

ECMA脚本不包含共享对象,但它有
SharedArrayBuffer
。您可以使用
DataView
和包装器在自己的缓冲区中直接写入数据时实现这种行为:

// Shared value
class SharedPoint {
  constructor(array) {
    this.dataview = new DataView(array);
  }

  set x(value) {
    this.dataview.setUint8(0, value);
  }

  set y(value) {
    this.dataview.setUint8(1, value);
  }

  get x() {
    return this.dataview.getUint8(0);
  }

  get y() {
    return this.dataview.getUint8(1);
  }
}

// Usage

const buffer = new SharedArrayBuffer(2);

// Create two instances of shared point.
const point0 = new SharedPoint(buffer);
const point1 = new SharedPoint(buffer);

// Get initial values for point #1
console.log('x', point1.x); // 0
console.log('y', point1.y); // 0

// Update point #0
point0.x = 64;
point0.y = 32;

// Get changes in point #1
console.log('x', point1.x); // 64
console.log('y', point1.y); // 32
您可以创建可以操作字符串或字符串的类。虽然
SharedArrayBuffer
是可传输对象,但它可以在工作进程和主进程之间共享

⚠️ 注由于
SharedArrayBuffer
被所有主要浏览器禁用,并从68版开始在Chrome中重新启用,从79版开始在Firefox中重新启用。检查上的浏览器支持


从我阅读的内容来看,唯一直接共享的内存是
SharedArrayBuffer
,它只包含原始二进制数据(而不是对象)。所以,我不知道如何在线程之间直接共享对象。工作线程的工作方式与浏览器中的web工作线程类似,在浏览器中没有共享的正则变量,它们必须通过
postMessage()
与其他代码通信(出于同步原因).将一段JSON放入
SharedArrayBuffer
似乎除了共享一个字符串之外没有多大帮助。每个worker必须
JSON.parse()
将JSON解析为自己的非共享对象。这种级别的共享可以通过在任何时候向每个工作人员发布一条消息来完成,只要有人想要更改数据,这样所有工作人员都有一个相同数据的副本