看完这节课的一些疑问
来源:34-2 什么是分布式锁

城中城
2022-06-28
老师你可以直接复制下面代码运行看看
或者自己改一下即可 在释放锁后 添加一个等待时间
from datetime import datetime
from peewee import *
from inventory_srv.settings import settings
# 删除 物理删除和逻辑删除 - 物理删除 - 假设你把某个用户数据 - 用户购买记录, 用户的收藏记录, 用户浏览记录啊
# 通过 save 方法做了修改 如何确保只修改 update_time 值而不是修改 add_time
class BaseModel(Model):
add_time = DateTimeField(default=datetime.now, verbose_name="添加时间")
update_time = DateTimeField(default=datetime.now, verbose_name="更新时间")
is_deleted = BooleanField(default=False, verbose_name="是否删除")
def save(self, *args, **kwargs):
# 判断这是一个新添加的数据还是更新的数据
if self._pk is not None:
# 这是一个新数据
self.update_time = datetime.now()
return super().save(*args, **kwargs)
@classmethod
def delete(cls, permanently=False): # permanently 表示是否永久删除
if permanently:
return super().delete()
else:
return super().update(is_deleted=True)
def delete_instance(self, permanently=False, recursive=False, delete_nullable=False):
if permanently:
return self.delete(permanently).where(self._pk_expr()).execute()
else:
self.is_deleted = True
self.save()
@classmethod
def select(cls, *fields):
return super().select(*fields).where(cls.is_deleted==False)
class Meta:
database = settings.DB
# class Stock(BaseModel):
# # 仓库表
# name = CharField(verbose_name="仓库名")
# address = CharField(verbose_name="仓库地址")
class Inventory(BaseModel):
# 商品的库存表
# stock = PrimaryKeyField(Stock)
goods = IntegerField(verbose_name="商品id", unique=True) # unique:在此列上创建唯一索引
stocks = IntegerField(verbose_name="库存数量", default=0)
version = IntegerField(verbose_name="版本号", default=0) # 分布式锁的一种 乐观锁
import threading
R = threading.Lock()
def sell():
# 多线程下的并发带来的数据不一致的问题
goods_list = [(421, 99), (422, 20), (423, 30)]
with settings.DB.atomic() as txn:
# 超卖
for goods_id, num in goods_list:
# 查询库存
R.acquire() # 获取锁 负载均衡
goods_inv = Inventory.get(Inventory.goods==goods_id)
print(f"商品{goods_id} 售出 {num} 件")
import time
from random import randint
time.sleep(randint(1, 3))
if goods_inv.stocks < num:
print(f"商品: {goods_id} 库存不足")
txn.rollback()
R.release() # 释放锁
break
else:
# 让数据库根据自己当前的值更新数据, 这个语句能不能处理并发的问题
query = Inventory.update(stocks=Inventory.stocks-num).where(Inventory.goods==goods_id)
ok = query.execute()
if ok:
print("更新成功")
else:
print("更新失败")
R.release() # 释放锁
time.sleep(1)
if __name__ == '__main__':
import threading
t1 = threading.Thread(target=sell)
t2 = threading.Thread(target=sell)
t1.start()
t2.start()
t1.join()
t2.join()
只是在老师的代码 稍微 更改一下 还是一样有着相同的问题
比如 我在释放锁后 等待一些时间
导致 线程1产生 io操作 被线程2争取
这样就比 超卖还要严重 导致锁无法被释放的问题
请问 这样如何解决
因为真正的生产环境中 极有可能会遇到这类问题
写回答
1回答
-
线程2拿到锁了, 线程二就扣减就行了, 为什么会导致锁无法释放?
022022-06-28
相似问题