【问题标题】:Which operations in node are thread safe?节点中的哪些操作是线程安全的?
【发布时间】:2012-04-18 17:31:29
【问题描述】:

我正在使用 this approach 将数据存储在一个全局数组中,该数组托管一个 http 服务器,其中某些请求将操纵全局数组。

我有点担心某些操作会遇到线程问题——主要是pushsplice。我想如果一个请求让我遍历数组并根据条件删除项目,而另一个请求让我在数组上调用.push(),我会遇到问题。谁能证实这一点?

我主要用 C# 编写,即使是简单的增量也不是线程安全的(启动 25 个执行 i++ 的线程,并不能保证 i == 25 毕竟说完就完事了)。

更新

我写了 5 个例子来说明我在说什么。测试 1 和测试 3 工作正常。测试 2 失败,因为……通常称为线程问题(无论它们是否是实际的 CPU 线程)。测试 4 和 5 在并行运行时似乎有效(这意味着它们没有像测试 2 那样的碰撞问题)。

http://pastebin.com/HcJHTDFY

我正在使用 ApacheBench 进行测试,发出 1000 个并行请求。

这让我相信测试 1 和测试 3 工作正常,因为 nodejs 不会并行执行超过 1 个 app.get('/test3'...) 回调的实例 javascript 函数并行(阻塞?)。一旦你实现了 setInterval/setTimeout,它就会释放 nodejs 来执行另一个回调实例(非阻塞?)。

我真的只是想了解non-blocking I/O model 的真正含义。这是否意味着“嘿,如果您需要非阻塞,可以使用 setTimeout 和 setInterval 进行非阻塞,否则我们将阻止任何其他外层函数运行,直到我们用完我们正在使用的函数” ?我觉得有必要知道这一点,这样我就不会陷入困境,以为我可以实现 /test2 之类的东西并且完全安全。

另外,如果我试图不阻塞我的回调,我真的应该打电话给setTimeout(code, 1)吗?还是有更好的办法?

【问题讨论】:

    标签: node.js


    【解决方案1】:

    所有都是线程安全的。

    没有线程,JavaScript是单线程的,两条javascript语句不可能同时运行。

    顺便说一句,你不应该使用全局变量,因为全局变量是邪恶的

    编辑:

    测试 2 失败,因为您使用的是异步回调,这意味着控制权返回到节点,它可以处理更多请求。正如所见,这会产生竞争条件。

    在节点中,任何非异步块。您唯一拥有的异步操作是 setTimeout/setInterval/process.nextTick 和任何异步 IO 操作。

    不应手动使计算异步。应该避免做太多的计算。

    我写了一篇关于What it means to be non-blocking的文章

    【讨论】:

    • 所以当 nodeJs/V8 进入我写的 function() { } 时,除了我在内部调用的函数(作为回调)之外,不会执行我的其他函数?
    • 顺便说一句,JavaScript 可能是单线程的,但 nodeJS 似乎是多线程的,否则对内置 http 服务器的后续请求将无法返回,直到第一个完成.还有stackoverflow.com/questions/7018093/…
    • @Langdon 是否是多线程的,这是您不应该关心的实现细节。它所做的只是异步 IO,直接在内核级别或使用线程池模拟异步 IO
    • @Langdon 你不在乎,你永远看不到线程。这就像问“SQL 线程安全吗?”。尽管 SQL 引擎实现在几层以下的某个地方使用了线程,但您永远看不到它们,也不关心它们,它们只是实现细节。
    • 我相信答案有点误导。这并不意味着它是线程安全的,即使它是单线程的,因为您仍然会遇到竞争条件,并且拥有线程并不意味着同时运行两条语句,除非您拥有多核处理器。人们会期望线程安全代码没有竞争条件。用户级线程和内核线程之间也存在差异。您可以在没有编程语言直接支持的情况下实现用户级线程。
    【解决方案2】:

    Raynos 基本上是正确的。但是仅仅因为 JavaScript 是单线程的并不意味着你可以放松警惕。您仍然需要了解线程。一个很好的例子来说明这一点,socket.io 如何与不同的客户端保持连接,并且仍然能够跟踪这些客户端。

    JavaScript 的函数式编程部分通过变量绑定工作(例如...很多)。不了解线程会使您错误地假设您的变量是正确绑定的。就像 socket.io 的例子一样,你怎么能确定你得到的连接是你认为你得到的客户端?如果引用绑定出错并且连接实际上引用了不同的客户端怎么办?

    这是你需要小心的事情。

    【讨论】:

    • JavaScript 没有通过引用传递。那和你谈论的废话与线程无关。如果操作系统在内核级别支持异步 IO,node.js 甚至不使用线程
    • 提供实际的反馈/批评。 “参考绑定何时出错”。连接何时会引用不同的“客户端”。是的,您应该注意并发陷阱,但您没有描述它们并且它们与线程无关
    猜你喜欢
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 2011-08-28
    • 2023-03-22
    • 2010-12-20
    • 1970-01-01
    • 2017-05-16
    相关资源
    最近更新 更多