避開死鎖
代碼程序中,盡量要避免死鎖的產生,下面分析常見的線程鎖使用方式 ;注:只有同一把鎖才會產生互斥
1、常見的死鎖方式(加鎖時程序報錯,鎖未釋放):
import time
import threading
class Lock():
def __init__(self):
self.mutex = threading.Lock()
def error(self):
try:
self.mutex.acquire()
a = '1'
b = 2
print(a+b)
self.mutex.release()
except Exception as e:
print(e)
def safe(self):
try:
self.mutex.acquire()
a = 1
b = 2
print(a + b)
self.mutex.release()
except Exception as e:
print(e)
def func1(cls):
while True:
cls.safe()
time.sleep(0.1)
def func2(cls):
while True:
cls.error()
time.sleep(0.1)
if __name__ == '__main__':
lock = Lock()
t1 = threading.Thread(target=func1,args=(lock,))
t1.start()
t2 = threading.Thread(target=func2,args=(lock,))
t2.start()
# 3
# must be str, not int
執行上面代碼,異常拋出時,鎖未釋放,程序卡死
2、修補代碼死鎖情況(拋異常處添加鎖釋放):
import time
import threading
class Lock():
def __init__(self):
self.mutex = threading.Lock()
def error(self):
try:
self.mutex.acquire()
a = '1'
b = 2
print(a+b)
self.mutex.release()
except Exception as e:
print(e)
self.mutex.release()
def safe(self):
try:
self.mutex.acquire()
a = 1
b = 2
print(a + b)
self.mutex.release()
except Exception as e:
print(e)
def func1(cls):
while True:
cls.safe()
time.sleep(0.1)
def func2(cls):
while True:
cls.error()
time.sleep(0.1)
if __name__ == '__main__':
lock = Lock()
t1 = threading.Thread(target=func1,args=(lock,))
t1.start()
t2 = threading.Thread(target=func2,args=(lock,))
t2.start()
# 3
# must be str, not int
# must be str, not int
# 3
# 3
3、最佳方案(不用手動釋放,即使異常也會自動釋放):
import time
import threading
class Lock():
def __init__(self):
self.mutex = threading.Lock()
def error(self):
try:
with self.mutex:
a = '1'
b = 2
print(a+b)
except Exception as e:
print(e)
def safe(self):
try:
with self.mutex:
a = 1
b = 2
print(a + b)
except Exception as e:
print(e)
def func1(cls):
while True:
cls.safe()
time.sleep(0.1)
def func2(cls):
while True:
cls.error()
time.sleep(0.1)
if __name__ == '__main__':
lock = Lock()
t1 = threading.Thread(target=func1,args=(lock,))
t1.start()
t2 = threading.Thread(target=func2,args=(lock,))
t2.start()
# 3
# must be str, not int
# 3
# must be str, not int
# 3
# must be str, not int
