一、互斥锁与死锁
1.1 互斥锁
互斥锁:对共享数据进行锁定,保证同一时刻只能有一个线程去操作,是多个线程一起去抢,抢到锁的线程先执行,没抢到的等待互斥锁使用完释放后再去抢
使用步骤
lock = threading.Lock() # 创建全局互斥锁
lock.acquire() # 上锁
# ……执行代码,保证同一时刻只有一个线程去操作,对共享数据进行锁定
lock.release() # 释放锁
- 互斥锁能保证多个线程访问共享数据不会出现数据错误问题
- acquire与release之间的代码同一时刻只能有一个线程去操作,能够确保某段关键代码只能由一个线程从头到尾完整执行
- 若调用acquire方法时其他线程已经使用了该互斥锁,acquire方法会堵塞,直至该互斥锁释放才能再上锁
- 加上互斥锁多任务瞬间变为单任务,影响代码执行效率,性能会下降,同一时刻只能有一个线程去执行
- 加上互斥锁,哪个线程抢到锁就先执行,其余的等待
- 若使用不当易出现死锁,要在合适的地方释放锁
举例如下:
lock = threading.Lock() # 创建全局互斥锁
sum = 0
def sum1():
lock.acquire() # 上锁
for i in range(1000000): # 实现一百万次全局变量加1
global sum
sum += 1
print('总和为:', sum, 'sum两倍为:', sum*2)
lock.release() # 释放锁
def sum2():
lock.acquire() # 上锁
for i in range(1000000):
global sum
sum += 1
print('总和为:', sum)
lock.release() # 释放锁
if __name__ == '__main__':
sum1_thread = threading.Thread(target=sum1)
sum2_thread = threading.Thread(target=sum2)
sum1_thread.start()
sum2_thread.start()
输出:
总和为: 1000000 sum两倍为: 2000000
总和为: 2000000
1.2 死锁
死锁:一直等待对方释放锁的情景,死锁会造成应用程序停止响应,不再处理其他任务,应用程序无法继续往下执行
举例如下:
import threading
import time
lock = threading.Lock() # 创建互斥锁
def getValue(i):
lock.acquire() # 上锁
print(threading.current_thread())
list = [0, 2, 5]
if i >= len(list):
print('下标为%d,已越界' % i)
return
print('下标为%d的值为:%d' % (i, list[i]))
time.sleep(0.2)
lock.release() # 释放锁
if __name__ == '__main__':
for i in range(5):
value_thread = threading.Thread(target=getValue, args=(i,))
value_thread.start()
输出:
<Thread(Thread-1, started 37860)>
下标为0的值为:0
<Thread(Thread-2, started 27920)>
下标为1的值为:2
<Thread(Thread-3, started 37420)>
下标为2的值为:5
<Thread(Thread-4, started 33532)>
下标为3,已越界
# 执行未结束,死锁状态
--------------------------避免死锁---------修改-------------
def getValue(i):
lock.acquire() # 上锁
print(threading.current_thread())
list = [0, 2, 5]
if i >= len(list):
print('下标为%d,已越界' % i)
lock.release() # 下标越界要释放锁,以让后面的线程继续可以取值
return
print('下标为%d的值为:%d' % (i, list[i]))
time.sleep(0.2)
lock.release() # 释放锁
输出:
<Thread(Thread-1, started 21816)>
下标为0的值为:0
<Thread(Thread-2, started 35400)>
下标为1的值为:2
<Thread(Thread-3, started 27992)>
下标为2的值为:5
<Thread(Thread-4, started 32780)>
下标为3,已越界
<Thread(Thread-5, started 25208)>
下标为4,已越界
# 正常结束
1.3 推荐学习
学习导航:http://xqnav.top/