Python-线程同步(锁)和死锁
线程同步
共享数据:
-
如果多个线程共同对某个数据修改,可能出现不可预料的结果,为了保证数据的安全性,需要对多个线程进行同步,一个一个的完成,一个做完另一个才能进来。 效率会降低。
多线程的优势在于可以同时运行多个任务,但是当线程需要共享数据时,可能存在数据不同步的问题。
为了避免这个问题,引入了锁的概念。
python对线程加锁主要有Lock和Rlock模块
使用Tread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。
Lock模块
用例
import threading from time import sleep lock = threading.Lock() list1 = [0] * 10 def task1(): # 获取线程锁,如果已经上锁,则等待锁的释放。 lock.acquire() # 阻塞 for i in range(len(list1)): list1[i] = 1 sleep(0.5) lock.release() def task2(): # 获取线程锁,如果已经上锁,则等待锁的释放。 lock.acquire() # 阻塞 for i in range(len(list1)): print("----->",list1[i]) sleep(0.5) lock.release() if __name__ == __main__: t1 = threading.Thread(target=task1) t2 = threading.Thread(target=task2) t2.start() t1.start() t2.join() t1.join() print(list1)
输出:
-----> 0 -----> 0 -----> 0 -----> 0 -----> 0 -----> 0 -----> 0 -----> 0 -----> 0 -----> 0 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Lock有acquire()和release()方法,这两个方法必须是成对出现的,acquire()后面必须release()后才能再acquire(),否则会造成死锁
死锁
开发过程中使用线程,在线程间共享多个资源的时候,如果两个线程占有一部分资源并且同时等待对方的资源,就会造成死锁。 尽管死锁很少发生,但是一旦放生就会造成应用停止响应,程序不做任何事情。
避免死锁:
-
重构代码 使用timeout参数
from threading import Thread,Lock from time import sleep lockA = Lock() lockB = Lock() class Mythread1(Thread): def run(self) -> None: # 执行start()方法自动寻找run()方法 if lockA.acquire(): # 如果可以获取到锁,返回True print(self.name+获取到A锁!) sleep(0.1) if lockB.acquire(timeout=1): # 阻塞,现在等待不到B锁,设定时间自动释放锁 print(self.name+又获取到了B锁!原来还有A锁!) lockB.release() lockA.release() class Mythread2(Thread): def run(self) -> None: # 执行start()方法自动寻找run()方法 if lockB.acquire(): # 如果可以获取到锁,返回True print(self.name+获取到B锁!) sleep(0.1) if lockA.acquire(): print(self.name+又获取到了A锁!原来还有B锁!) lockA.release() lockB.release() if __name__ == __main__: t1 = Mythread1() t2 = Mythread2() t1.start() t2.start() t1.join() t2.join() print(结束!!!!!!!!!!!!!)
输出:
Thread-1获取到A锁! Thread-2获取到B锁! # 此处Thread-1等待B锁因为timeout=1等待1秒后,自动释放了 Thread-2又获取到了A锁!原来还有B锁! 结束!!!!!!!!!!!!!
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
程序员的职业路线规划