nodejs 里多个定时任务里用到相同的变量, 会不会有线程安全的问题?

2022-10-04 11:22:25 +08:00
 bthulu

这里在做一个制造厂内物流调度方案, 调度系统用的 js 的 setTimeout 无限循环.

每条流水线就会有一个无限循环的 setTimeout.

所有流水线上的货物, 机器设备的运行状态, 都统一保存在一个 store 中. 这些数据是从另一个与硬件直接通信的后台上定时轮询获取的.

流水线之间的货物是会相互流通的, 并且这个流水线的货物的大小状态, 会影响另一个流水线的运行状况. 因此就会出现流水线之间的调度线程访问相同设备或货物的情况, 并根据当前状态改变流水线的运行状态.

综上, 这个 store 是会在不同线程中批量或单独读取写入的, 那么, 有什么办法保证批量或单独读写的原子性吗? 还是说 js 天然就是线程安全的, 完全不用管这个?

按说 setTimeout 的回调函数都是在一个线程里执行的, 但是会不会出现某个回调函数执行一半, 碰到个 await 了, 就跳过去执行另一个回调函数, 然后再跳回来? 那这样这个带 await 的函数就被另一个函数插了一脚. 如果另一个函数访问了这个带 await 函数会修改的变量, 岂不是读到了脏数据?

2375 次点击
所在节点    JavaScript
5 条回复
dcsuibian
2022-10-04 11:59:15 +08:00
Javascript 不都是单线程的么,除非你用 worker
lmshl
2022-10-04 11:59:23 +08:00
普通函数,非 await 代码块是不会给你切换出去的,100%连续执行你可以放心。
但是 async 函数是一定会切出去的,再切回来之前执行过什么无法保证。所以必然会遇到脏数据。

所以,请将涉及共享数据修改的代码设计成尽可能连续的操作
或不使用可变数据
或考虑使用自旋重试
或使用其他串行化方案,比如加 mutex
ochatokori
2022-10-04 14:10:39 +08:00
await 如果我等待的是微任务,那是不会跳到别的 settimeout 宏任务的,但是这个你不好控制。

可以用 while/for 代替 setTimeout 去无限循环,就能保证每次循环里就算 await 也能顺序执行
xavierchow
2022-10-04 23:59:04 +08:00
> 综上, 这个 store 是会在不同线程中批量或单独读取写入的, 那么, 有什么办法保证批量或单独读写的原子性吗?

不太清楚你这个 store 是什么,如果你有多个 node.js application 需要共享数据,最直接的就是把数据放在 database ( redis 也行)里,由 database 来保证原子性。
zegko
2022-10-05 11:13:47 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/884591

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX