在Rails中不是线程安全的东西的示例

Vor*_*ane 7 ruby-on-rails thread-safety class-variables

我见过像线程对线程安全的Rails以及有关这一主题的各种网页,我敢肯定,每个人都在背诵它是什么,给什么不是线程安全的("类变量"秘诀"是伟大的!"),但我似乎永远无法在Rails中找到一个实际上不是线程安全的东西的清晰,简单,完整的例子,我想知道是否有人真正了解它.

如果有人可以证明我错了并给予:我将不胜感激:

  • 一个清晰,简单,完整的例子,它在Rails中不是线程安全的.应该清楚代码的位置(即,如果它在控制器中,请显示它)并且不应该留给读者的想象(例如不存在的方法).此外,不应该有任何多余的代码或逻辑.

  • 确切地说,两个用户在两个不同的线程上同时连接到网站的情况下会出现问题.

  • 如何纠正这个问题.

更重要且与Rails相关的示例越好,所以如果您可以举例说明一个用户可能会看到另一个用户的数据(或类似数据),请执行此操作.

Joe*_*lum 0

注意
这只是部分答案,因为它是一个陈旧的读取示例(这可能是由多进程和多线程引起的),OP 似乎只是在寻找多线程问题

假设您有一家商店向用户出售商品并相应地更新他的余额。

 PaymentsController

    if current_user.balance > item.price 
       current_user.balance = current_user.balance - item.price #1
       current_user.create_purchase(item)  #2
       current_user.save #3
    end
Run Code Online (Sandbox Code Playgroud)

这里潜在的问题是,在条件内部(假设在第 #1 行或第 #2 行中)线程可以切换到不同的线程,完全运行,当我们返回到原始线程时(仍然卡住),余额现在是不同的值在第 #1 行)它不知道这已经发生了!它可能允许余额不足的用户进行购买,并且还会用错误的值覆盖实际余额。

这是如何发生这种情况的更具体示例

让我们想象一下,用户试图通过购买超出其余额允许的数量来欺骗我们的系统。项目 1 的成本为 100,项目 2 的成本为 75,他的余额为 100。

用户编写一个脚本来触发 2 个帖子请求来购买这些物品,这样他们就几乎得到了同时到达应用服务器。第一个请求到达第 1 行,在第 #2 行之前,线程切换到请求 2。第二个请求完全运行,没有中断 - 它购买第二个项目,因此新的实际余额现在为 25 (100 - 75)。现在上下文切换到请求 1。请求 1 没有意识到实际余额是 25(它仍然认为用户有足够的余额来购买该商品:请记住,请求 1 在条件内的第 2 行切换!请求 1完成购买,然后将余额更新为 0 (100 - 100)。用户刚刚购买了两种产品,其价格超出了其余额应允许的范围!

处理这种情况的一种方法是锁定http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html