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

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

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

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

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

  • 如何纠正这个问题。

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

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

在这里,假设您有一个商店向用户销售商品并相应地更新其余额。

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个post请求购买这些项目,以便它们几乎同时到达应用服务器。 第一个请求命中第1行,第2行直到第2行线程切换到请求2​​.第二个请求完全没有中断运行 – 它购买第二个项目,因此新的实际余额现在是25(100 – 75)。 现在上下文切换到请求1.请求1没有意识到真正的余额是25(它仍然认为用户有足够的余额来购买项目:记住请求1在第2行切换,在条件内!请求1完成购买,然后将余额更新为0(100 – 100)。用户只买了两件价格超过其余额的产品应该允许!

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