持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天
多线程同步
数据共享
如果多个线程同时对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步(一个一个的完成)
使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。
多线程的优势在于可以同时运行多个任务(感觉起来的样子)。但是当多线程要共享数据时,可能存在数据不同步问题,为了避免这种情况,引入了锁的概念
怎么用呢?
lock = threading.Lock() #创建一个锁的对象
lock.acquire() #得到锁,阻塞
......
lock.release() #释放锁
import threading
import time
lock = threading.Lock()
list1 = [0] * 10
def task1():
#获取线程锁,如果已经上锁,则等待锁的释放
lock.acquire() #阻塞
for i in range(len(list1)):
list1[i] = 1
time.sleep(0.5)
lock.release() #释放锁
def task2():
lock.acquire() #阻塞
for i in range(len(list1)):
print('--->',i)
time.sleep(0.5)
lock.release() #释放锁
if __name__ == '__main__':
t1 = threading.Tread(target=task1)
t2 = threading.Tread(traget=task2)
t1.start()
t2.start()
死锁
是那么是死锁
开发过程中使用线程,在线程之间共享多个资源的时候,如果有两个线程分别占用一部分资源并且同时等待对方的资源,这会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用停止响应,程序不做任何事情。
- 这个是死锁的示例(错误示范)
from threading import Thread.lock
import time
lockA = Lock()
lockB = Lock()
class MyThread(Thread):
def run(self):
if lockA.acquire():
print(self.name)
time.sleep(0.1)
if lockB.acquire():
print(self.name+'又获取了B锁,原来还有A锁')
lockA.release()
class MyThread1(Thread):
def run(self):
if lockB.acquire():
print(self.name+'获取了B锁')
time.sleep(0.1)
if lockA.acquire():
print(self.name+'又获取了A锁,原来还有B锁')
lockA.release()
lockB.release()
if __name__ == '__main__':
t1 = MyThread()
t2 = MyThread1()
t1.start()
t2.start()
于是就形成了上述的情况,线程A在阻塞恢复后想拿锁B但是被线程2拿了导致线程1不动,而线程2也因为1不动而不动(即B锁拿到了释放后才能释放A锁,而B锁也是同理,但两个线程分别占着锁,所以导致AB均不能释放,所以形成了死锁)