Python 项目中使用锁的常见问题及解决方法

在 Python 多线程编程中,锁是保证共享资源安全访问的核心机制。然而,锁的不当使用往往会引发新的问题,如死锁、性能损耗等。本文结合实际项目场景,深入剖析锁在使用过程中的常见问题,并提供可落地的解决方法。

一、死锁:线程间的无限等待

1.1 交叉锁竞争导致死锁

问题表现

当两个或多个线程相互持有对方需要的锁,并无限期等待时,就会发生死锁。例如在电商订单处理场景中,线程 A 持有订单锁并等待库存锁,线程 B 持有库存锁并等待订单锁,双方陷入永久阻塞。

 

import threading

import time

order_lock = threading.Lock()

inventory_lock = threading.Lock()

def process_order():

with order_lock:

print("线程A获取订单锁,等待库存锁")

time.sleep(1) # 模拟订单处理耗时

with inventory_lock:

print("线程A获取库存锁,处理订单")

def update_inventory():

with inventory_lock:

print("线程B获取库存锁,等待订单锁")

time.sleep(1) # 模拟库存查询耗时

with order_lock:

print("线程B获取订单锁,更新库存")

t1 = threading.Thread(target=process_order)

t2 = threading.Thread(target=update_inventory)

t1.start()

t2.start()

解决方法:统一锁获取顺序

所有线程严格按照预设的顺序获取锁,消除交叉等待条件。例如规定必须先获取订单锁,再获取库存锁。

 

def process_order_safe():

with order_lock:

print("线程A获取订单锁")

time.sleep(1)

with inventory_lock:

print("线程A获取库存锁,处理订单")

def update_inventory_safe():

with order_lock: # 先获取订单锁,再获取库存锁

print("线程B获取订单锁")

time.sleep(1)

with inventory_lock:

print("线程B获取库存锁,更新库存")

1.2 递归锁使用不当引发死锁

问题表现

在递归调用场景中,使用普通互斥锁(Lock)会导致同一线程重复获取锁时发生死锁。例如在树形结构遍历中,递归函数需要多次访问共享资源。

 

data_lock = threading.Lock()

def recursive_traverse(node):

with data_lock: # 第一次获取成功

print(f"处理节点 {node}")

if node.children:

recursive_traverse(node.children[0]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值