V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
bthulu
V2EX  ›  JavaScript

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

  •  
  •   bthulu · 2022-10-04 11:22:25 +08:00 · 2394 次点击
    这是一个创建于 791 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

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

    不太清楚你这个 store 是什么,如果你有多个 node.js application 需要共享数据,最直接的就是把数据放在 database ( redis 也行)里,由 database 来保证原子性。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1022 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 20:45 · PVG 04:45 · LAX 12:45 · JFK 15:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.