首页 > 解决方案 > 我应该如何避免这种竞争条件?

问题描述

我有一段如下代码,为简洁起见被截断:

        bargained_count = BargainLog.objects.filter(bargain_start_log=bargain_start_log).count()
        ...
        money = calc_single_bargain_money(
            bargained_count=bargained_count,
            ......
        )
        ...
        BargainLog.objects.create(bargain_start_log=bargain_start_log, money=money, ...)

bargained_count是 func 的参数calc_single_bargain_money。但是,由于比赛条件,我不确定这是否是一种比赛条件。我可能会bargained_count在高并发下获得相同的值,这会影响calc_single_bargaiN_money. 所以,我应该如何避免它,请给我一些建议。

就像在多线程中一样,我想在获取之前添加一个锁,bargained_count并在创建新实例之后释放锁,BargainLog以确保它们捆绑在一起。

我曾尝试使用 celery 来处理这个问题,但由于参数传递导致它不方便。

标签: djangodjango-rest-frameworkrace-condition

解决方案


您可以使用.select_for_update()锁定行直到事务结束。在此处查看文档

from django.db import transaction


bargain_logs = BargainLog.objects.filter(bargain_start_log=bargain_start_log).select_for_update()

with transaction.atomic():
    bargained_count = bargain_logs.count()
    ...
    money = calc_single_bargain_money(
        bargained_count=bargained_count,
        ......
    )
    ...
    BargainLog.objects.create(bargain_start_log=bargain_start_log, money=money, ...)

推荐阅读