从两个不同的 Worker 线程调用的 console.log() 是否可以相互踩踏,或者它们总是一个接一个?

Can console.log()s called from two different Worker threads ever step on each other, or are they always one after the other?

我有一小段示例代码:

//main.js

const {Worker} = require("worker_threads");

const worker = new Worker("./background.js", {workerData: {}});

function loop() {

    console.log("main: 1234567890");
    setTimeout(loop, 0)

}

loop();

并且:

//background.js

const {parentPort, workerData} = require("worker_threads");

function loop () {

    console.log("background: 1234567890");
    setTimeout(loop, 0)

}

loop();

运行 像这样:node main.js

输出是这样的:

background: 1234567890
main: 1234567890
background: 1234567890
main: 1234567890
background: 1234567890
background: 1234567890
#etc

有时,一个线程中的多个 console.log() 会先于另一个线程调用。这是预期的,很好。

但是 console.log() 是否有可能在另一个 console.log() 的中间 被调用 ?例如,这会发生吗?

background: 123main: 12345456786789090

我没有在我的输出中观察到它,但我想从规范来源知道 Workers/console.log() 在 node.js.[= 中不那样工作16=]

console.log() 对于基元(非对象)是线程安全的。因此,在您传递字符串的特定示例中,这是安全的,您不会混淆输出。

但是,如果您将一个对象传递给 console.log(obj) 并且线程正在修改该对象,那么在将对象转换为输出并编组到日志输出之前可能会出现问题。这甚至可能只发生在一个线程中,您可以在其中立即修改后续代码行中的对象。

这显然是因为对象到控制台输出的转换是“惰性的”而不是即时的。这可能是为了尽量减少调用 console.log() 对性能的影响而并行 运行 的尝试。我在实际代码中看到过这一点,解决方法是调用 console.log(JSON.stringify(obj)) 而不是 console.log(obj) 来消除对象在延迟记录之前被修改的任何问题。