Python线程锁
多线程用于IO、网络请求等地方,只要不是CPU密集型,都可以直接使用多线程。
线程锁在代码中发挥着关键的保护作用,让我详细解释它的工作原理:
锁的作用机制
1. 基本工作原理
with lock:
if ensp_id in ensp_to_seq:
return True
执行流程:
- 线程A进入
with lock:块,获取锁 - 线程A检查
ensp_id是否在字典中 - 在此期间,线程B尝试进入同一个
with lock:块,但被阻塞等待 - 线程A完成检查后退出
with块,自动释放锁 - 线程B现在可以获取锁并进入临界区
2. 为什么需要锁?
没有锁的情况(竞态条件):
# 线程A检查 ensp_id 不在字典中
if ensp_id not in ensp_to_seq: # 假设此时不在
# 在线程A发起请求前,线程B也检查同一个ensp_id
# 线程B也发现不在字典中,也发起请求
# 结果:同一个ensp_id被请求了两次!
有锁的情况:
with lock:
if ensp_id in ensp_to_seq: # 线程A检查,获取锁
return True
# 线程A释放锁,发起请求...
# 线程B必须等待线程A完成检查才能进入
3. 完整的线程安全流程
def get_ensembl_sequence(ensp_id: str):
# 第一步:检查是否存在(需要锁保护)
with lock:
if ensp_id in ensp_to_seq: # 原子性操作
return True
# 第二步:网络请求(不需要锁,可以并行执行)
headers = {"Content-Type": "text/x-fasta", "Accept": "text/x-fasta"}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
seq = response.text.strip()
seq = "".join(seq.split("\n")[1:])
# 第三步:写入结果(需要锁保护)
with lock:
ensp_to_seq[ensp_id] = seq # 原子性操作
print(len(ensp_to_seq))
return True
except:
return False
关键点:锁确保了检查-写入操作的原子性,避免了竞态条件,保证了数据的一致性。

浙公网安备 33010602011771号