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

时间:2016-07-26 10:39:14

标签: ruby-on-rails thread-safety class-variables

我在Rails中看到了关于线程安全的this之类的线程以及关于该主题的各种网页,我确信每个人都很擅长朗读它是什么,并给出了关于什么不是什么的'提示'线程安全(“类变量!”),但我似乎永远无法找到一个清晰,简单,完整的例子,在Rails中实际上不是线程安全的 ,我想知道这一点如果有人真的理解它。

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

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

  • 在两个用户同时在两个不同线程上连接到网站的情况下,究竟会出现问题。

  • 如何纠正问题。

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

1 个答案:

答案 0 :(得分: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

这里潜在的问题是在条件内(比如在行#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