Python死锁产生原因及解决方法
死锁:并发下,线程因为相互等待对方的一个资源,导致永久阻塞的现象。
产生原因
1.互斥:共享资源只能被一个线程占用;–互斥锁
2.占有且等待:线程当前至少占有一个资源,并且还想请求其他线程持有的其他资源就会造成等待。—等待对方释放资源。
3.不可抢占:资源只有由持有它的线程自愿释放,其他线程不可强行占有该自愿。—无法释放对方资源。
4.循环等待:线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,即循环等待。—两个线程互相等待。
解决办法
1.加锁顺序:加锁顺序是避免死锁的重要方法之一。如果多个线程总是按照相同的顺序请求锁,那么就不会出现死锁的情况。
import threading
lock_a = threading.Lock()
lock_b = threading.Lock()
def foo():
with lock_a:
with lock_b:
# do something
def bar():
with lock_a:
with lock_b:
# do something
2.使用try-except-finally,不管有没有异常,finally中都释放锁。
import threading
lock = threading.Lock()
def foo():
try:
with lock:
# do something
except:
print("出现异常")
finally:
lock.release()
3.使用超时机制:lock.acquire(timeout=5)设置获取锁的超时时间,若规定时间内取法获取锁,就放弃获取锁并执行其他操作。
import threading
lock_a = threading.Lock()
lock_b = threading.Lock()
def foo():
while True:
if lock_a.acquire(timeout=1):
# do something
if lock_b.acquire(timeout=1):
# do something
lock_b.release()
lock_a.release()
break
4.使用RLock: Python中的RLock是可重入锁,与普通锁不同的是,同一个线程可以多次获取同一个RLock,而不会出现死锁的情况。
# 在这个例子中,每个线程都可以多次获取同一个RLock,而不会出现死锁的情况
import threading
lock = threading.RLock()
def foo():
with lock:
# do something
with lock:
# do something
def bar():
with lock:
# do something
with lock:
# do something