【问题标题】:How to deal with a race condition如何处理竞争条件
【发布时间】:2015-12-13 19:54:50
【问题描述】:

我对 Web 开发还很陌生。从我读到的关于竞争条件的内容中,我认为使用节点或 JS 是不可能的,因为它是单线程的,但我认为那是……我猜错了。有人可以通过这个小例子解释它是如何工作的。

如果有一个银行账户,里面有 1000 美元,并且两个人在同一秒同时访问服务器,从该账户中扣款。第一个人收费 600 美元,第二个人收费 200 美元。

第一次收费为 1000 美元 - 600 美元,余额为 400 美元。 但是由于第二次收费是在同一时间发生的,所以它会产生 1000 美元到 200 美元的费用,而余额则为 800 美元。显然现在余额应该是 200 美元。

据我了解,这会导致竞争条件,不是吗?你将如何设置它来避免这个问题?我不需要确切的代码,也许有人向我解释一下,或者伪代码。

提前致谢。

编辑:我将对其进行编辑,以了解如何设置最初导致竞争条件的代码。

就像下面的帖子所说的那样。将设置代码,以便当账户被击中时,它会减去金额并给出新的余额。显然这会导致竞态条件。

【问题讨论】:

  • 您需要考虑您正在使用的数据库以及您如何编写 SQL 语句。请参阅以下(上一个)答案:stackoverflow.com/questions/22561241/…
  • 那么MongoDB数据库不适合这种类型的事情吗?

标签: javascript node.js race-condition single-threaded


【解决方案1】:

如果没有看到正在使用的确切代码,则无法具体回答您的示例,因为编写该代码的方法有安全,而编写该代码的方法不安全。

node.js 是单线程的,但只要一个请求进行异步调用,其他请求就可以在执行该异步请求时运行。因此,您可以同时处理多个请求。这是否会导致“竞争条件”完全取决于您编写代码的方式,在您的特定情况下,还取决于您访问数据库的方式。

如果你写这样的代码(伪代码):

 get total from database
 subtract from total
 write new total to database

而且,对数据库的调用是异步的(它们可能是异步的),那么您肯定会遇到竞争条件,因为在您获取总数和写入总数之间,其他请求可能会尝试访问相同的总数值并尝试修改它,一个请求要么没有最新的总值,要么两者会相互影响对方的结果(一个覆盖另一个)。

另一方面,如果您有一个数据库可以对数据库中的总值进行原子修改,如下所示:

subtract x from total in database

然后,您将免受该特定竞争条件的影响。


因为 node.js 是单线程的,所以在 node.js 中编写安全代码并不像在多线程 Web 服务器中那样复杂。这是因为只有一条 Javascript 路径同时执行。因此,除非您进行某种异步 I/O 调用,否则不会同时运行其他请求。这使得访问 node.js 应用程序中的共享变量比在真正的多线程 Web 服务器环境中更简单,在真正的多线程 Web 服务器环境中,对共享变量的任何访问都必须由互斥锁(或类似的东西)保护。但是,一旦您进行了异步调用,您必须意识到此时其他请求可以运行。

【讨论】:

  • 当然,如果您有 2 笔 600 美元的转账,您可能会遇到另一个问题,即余额现在为负数。
  • 您能否解释一下可以进行更多原子修改或提供阅读材料的数据库?
  • @jscriptnoob - 这是 sql 的主要功能之一(您可以编写在服务器上自动运行的逻辑)。有关一些信息,请参阅dev.mysql.com/doc/refman/5.1/en/ansi-diff-transactions.html。否则,您可能必须在数据库的某些部分上获取锁,如:获取锁、读取、修改、写入、解锁。也值得一读:en.wikipedia.org/wiki/Atomicity_(database_systems)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
  • 2020-07-12
  • 2011-04-01
  • 2014-02-23
相关资源
最近更新 更多