下面是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
块中以真正避免竞态条件?
1条答案
按热度按时间m528fe3b1#
with_lock
在生成块之前重新加载对象,来自文档:将传递的块 Package 在事务中,在产生之前用锁重新加载对象。
文档中的
with_lock
示例(几乎)相当于:字符串
reload
调用确保从数据库更新对象的属性。