ruby Rails文档中悲观锁定示例中的竞争条件

fzwojiic  于 5个月前  发布在  Ruby
关注(0)|答案(1)|浏览(49)

下面是Rails documentation的例子:

account = Account.first
account.with_lock do
  # This block is called within a transaction,
  # account is already locked.
  account.balance -= 100
  account.save!
end

字符串
我的理解是,first方法直接从数据库返回一条记录,而不是一个关系(类似于find)。现在假设balance = 200,我们有两个并发请求,它们都在到达with_lock块之前执行account = Account.first。两个请求现在都在内存中有200
然后,一个请求锁定了记录并将balance修改为100。但是当它解锁记录时,第二个请求将不会再次读取balance,但它将具有旧的200值,因此在这种情况下我们仍然会遇到竞态条件。所以我的问题是,是否应该将account = Account.first也 Package 在with_lock块中以真正避免竞态条件?

m528fe3b

m528fe3b1#

with_lock在生成块之前重新加载对象,来自文档:
将传递的块 Package 在事务中,在产生之前用锁重新加载对象。
文档中的with_lock示例(几乎)相当于:

account = Account.first
account.transaction do
  account.reload(lock: true)
  account.balance -= 100
  account.save!
end

字符串
reload调用确保从数据库更新对象的属性。

相关问题