Pay attention to sharing variables when Node processes in parallel

I encountered a strange bug at work this week. After searching for a long time, I found that it was the reason why a shared object variable was tampered with during parallel computing

Directly upload the code first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const Promise = require('bluebird');
const _ = require('loadsh');

function testForObject (obj, change) {
console.log(`=berfore: ${obj.test}=`);
obj.test = change;
console.log(`=after: ${obj.test}=`);
}

function testForCloneObject (obj, change) {
let cloneObj = _.cloneDeep(obj);
console.log(`=berfore: ${cloneObj.test}=`);
cloneObj.test = change;
console.log(`=after: ${cloneObj.test}=`);
}

const start = async function () {
const extParams = {
test: 10
}
const indexs = [1, 2];
Promise.map(indexs, (index) => {
testForObject(extParams, index);
}, {concurrency: 3});
}


const start2 = async function () {
const extParams = {
test: 10
}
const indexs = [1, 2];
Promise.map(indexs, (index) => {
testForCloneObject(extParams, index);
}, {concurrency: 3});
}

start();
// =berfore: 10=
// =after: 1=
// =berfore: 1=
// =after: 2=

start2();
// =berfore: 10=
// =after: 1=
// =berfore: 10=
// =after: 2=

According to the results, we can see that if the passed variables are not deeply copied, the modifications to the same passed object variables between different processes will affect each other. This is because in js, object variables are passed in when passing parameters. It is a reference, so if you directly modify an passed object parameter, it will lead to this situation.

Moreover, in this case, even if the object parameter you pass is const, it is useless, because const only guarantees that the reference address of the variable is unchanged, and there is no constraint on the value stored in the address.

The best way is to directly perform deep copying after passing in parameters.