线程锁
多线程修改数据会造成混乱
from threading import Thread
import time
x = 0
def task():
global x
for i in range(100000): # 最少10万级别才能看出来
x = x+1 # 有可能右边的x刚拿到了0,
# 发生线程不安全的原因:
# t1 x+1 阶段 x = 0 保存了状态 cpu被切走 t2 x+1 x = 0 保存了状态 cpu被切走
# 下次t1 继续运行代码 x = 0+1 下次t2 再运行代码的时候也是 x = 0+1
# 也就说修改了两次 x 只加了一次1 。
# time.sleep()
# lock.release()
if __name__ == '__main__':
t_list = []
for i in range(3):
t = Thread(target=task)
t_list.append(t)
t.start()
for i in t_list:
i.join()
print(x)
使用线程锁解决线程修改数据混乱问题
from threading import Thread,Lock
x=0
mutex=Lock()
def task():
global x
mutex.acquire()
for i in range(200000):
x=x+1
mutex.release()
if __name__ == '__main__':
t_list=[]
for i in range(3):
t=Thread(target=task)
t_list.append(t)
t.start()
for i in t_list:
i.join()
print(x)
死锁问题
from threading import Thread,Lock
mutex1=Lock()
mutex2=Lock()
import time
class MyThread(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
mutex1.acquire()
print(f'{self.name}抢到了 锁1')
mutex2.acquire()
print(f'{self.name}抢到了 锁2')
mutex2.release()
print(f'{self.name}释放了 锁2')
mutex1.release()
print(f'{self.name}释放了 锁1')
def task2(self):
mutex2.acquire()
print(f'{self.name}抢到了 锁2')
time.sleep(1)
mutex1.acquire()
print(f'{self.name}抢到了 锁1')
mutex1.release()
print(f'{self.name}释放了 锁1')
mutex2.release()
print(f'{self.name}释放了 锁2')
for i in range(3):
t=MyThread()
t.start()
# 两个线程
# 线程1拿到了(锁头2)想要往下执行需要(锁头1),
# 线程2拿到了(锁头1)想要往下执行需要(锁头2)
# 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁头.
死锁问题解决方法
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
from threading import Thread,RLock
# 递归锁 在同一个线程内可以被多次acquire
# 如何释放 内部相当于维护了一个计数器 也就是说同一个线程 acquire了几次就要release几次
mutex1=RLock()
mutex2=mutex1
import time
class MyThread(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
mutex1.acquire()
print(f'{self.name}抢到了 锁1')
mutex2.acquire()
print(f'{self.name}抢到了 锁2')
mutex2.release()
print(f'{self.name}释放了 锁2')
mutex1.release()
print(f'{self.name}释放了 锁1')
def task2(self):
mutex2.acquire()
print(f'{self.name}抢到了 锁2')
time.sleep(1)
mutex1.acquire()
print(f'{self.name}抢到了 锁1')
mutex1.release()
print(f'{self.name}释放了 锁1')
mutex2.release()
print(f'{self.name}释放了 锁2')
for i in range(3):
t=MyThread()
t.start()