1
yyfearth 2020-11-10 02:46:38 +08:00
我记得好像 console.log 有 buffer
|
2
mingl0280 2020-11-10 06:51:42 +08:00
没人告诉过你线程的执行顺序看操作系统当时状态决定么?!谁告诉你线程执行序有保证的?!
|
3
hgjian OP @mingl0280 我是觉得,应该是
顺序应该是 a 函数的 worker.postMessage( { } ) 触发 b 函数 执行 parentPort.postMessage( { } ) ; 执行完 b 的 parentPort.postMessage( { } ) ; 才会触发 主线程的 worker.on 函数; 请教一下,难道不是这样吗? |
5
yyfearth 2020-11-10 09:39:47 +08:00 1
我记得 console.log 有 io 的 buffer
所以可能 console.log 输出的时候比实际晚 依旧是说 你 call parentPort.postMessage( { } ) 的时候 console 还在 buffer 里面 然后不同的 worker buffer 不共享 所以两者的输出穿插了 当然这只是我的猜测 你可以不用 console.log 用别的方法试试 比如直接输出 stdout 并且 flush |
6
misdake 2020-11-10 09:51:35 +08:00 1
我觉得可能的一种 145623 的运行顺序:(不保证正确)
第一个 console.log(1)的时候,发起了刷 buffer 的请求,输出 1 。接下来的 bcde 因为没赶上这次的输出,被压进了主线程的 buffer,等待下一次刷新。 worker 线程在跑的时候,1“正在”输出,刷新时 worker 线程的 buffer 里已经有 456 了,输出 456 。(猜测不同线程的刷新是轮询的,而不是优先盯着一个) 下次刷主线程 buffer 的时候,buffer 里有 23,输出 23 。 如果在 isMainThread 判断之前加上一句 console.log ,提前刷一下 console.log 的 buffer,输出的顺序应该就和你想象的一样了。感觉就是 buffer 相关的原因。 |
9
hgjian OP @misdake
如果在 isMainThread 判断之前加上一句 console.log ,提前刷一下 console.log 的 buffer,输出的顺序应该就和你想象的一样了。 ===>> 在好几个地方 提前加了 console.log ,输出还是乱的,没有效果,我再研究看看有没有别的办法 |
10
des 2020-11-10 11:21:38 +08:00 1
写是有 buffer 的,想要得到你预期的结果
请使用 fs.writeFileSync(0, 'stdout: ' + msg + '\n'); |
11
libook 2020-11-10 11:30:16 +08:00 1
举个例子吧:
你手里有 1 元、2 元、5 元的三张纸币,我手里有 10 元、20 元、100 元三张纸币,你走到一个存钱罐前,喊我过去和你一起把各自手里的纸币按照各自的从小到大顺序塞进存钱罐,但是存钱罐每次只能塞一张纸币,所以咱俩只要没有人堵着投币口就可以往里面塞,因为没有对双方塞入的顺序进行控制,所以一开始可能是我塞入第一张也可能是你塞入第一张,而且有可能是一个人塞得快连续塞入两张纸币第另个人才有机会塞入一张,也可能一个人在塞入某一张的时候卡住了需要更多时间调整姿态,另一个人得等着……总之,你就是没法确定你是第一个塞入 1 元的,我也没法确定我啥时候能塞入第一账;但是我们都能确定,你自己塞入的顺序一定是 1 元、2 元、5 元,我自己塞入的顺序一定是 10 元、20 元、100 元。 引入多线程之后,就会有一个问题叫做“线程安全”,因为多个线程是同时运行的,所以在你没有特别控制执行顺序或确保最终一致性的措施的情况下,两个线程的执行顺序是不确定的,取决于你的操作系统和硬件当时是如何调度的。 也就是说,只要你开辟了新的线程,就不要尝试去判断新线程里的程序啥时候执行。 你可以判断同一线程内的执行顺序,比如 123 就是 123,不可能是 132,456 也一定是 456,不可能是 465 。 |
12
mingl0280 2020-11-10 12:04:21 +08:00 1
@hgjian 线程 1 你 post 完 message 以后就是两个线程并行执行的……worker.on 又没说哪里来的 message (我估计这个 post 直接给两个函数都发送了信号)
|
16
zy445566 2020-11-10 17:48:27 +08:00
用[ncpu]( https://github.com/zy445566/ncpu)使用 await 可以保证顺序,但是如果要保证性能最大肯定也是 Promise.all 来 ncpu 的任务。也可以使用同一个 ncpuWorker 来保证执行顺序
|
17
zy445566 2020-11-10 17:50:26 +08:00
上面链接多打了个空格导致 markdown 没识别,正确地址是: https://github.com/zy445566/ncpu
|
18
zy445566 2020-11-10 18:04:30 +08:00
其实线程安全主要是集中在 CPU cache 的问题,因为 CPU cache 速度比内存要快,所以会从内存中复制一份数据到 CPU cache 中,运算完成之后再复制回内存。
所以如果是单线程这样是没问题的,但是如果是多线程,就会出现一个时间差,比如两个线程先后复制到 CPU cache 中,但是计算完成后,再先后复制回内存。而这个时间差就会导致,一个线程计算的值不是另一个线程计算完成后的值,导致的线程不安全。 但 JS 也有《 SharedArrayBuffer API 提供 Atomics 对象,保证所有共享内存的操作都是“原子性”的。》--这句话引用自阮一峰的 ECMAScript 6 入门 |