多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)但是当线程需要共享数据时,可能存在数据不同步的问题。为了避免这种情况,引入了锁的概念。
1 lock = threading.Lock() 2 lock.acquire() # 请求得到锁 3 lock.release() # 释放锁 4 只要不释放其他的线程都无法进入运行状态
1、初始程序:
import threading import random import time lock = threading.Lock() list1 = [0] * 10 # [0,0,0,0,0,0,0,0,0,0] def task1(): for i in range(len(list1)): list1[i] = 1 # random.randint(1, 100) time.sleep(0.5) print(list1) def task2(): for i in range(len(list1)): print(f'当前的值是{i}') time.sleep(0.5) if __name__ == '__main__': t1 = threading.Thread(target=task1) t2 = threading.Thread(target=task2) t1.start() t2.start()
运行结果:
当前的值是0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 当前的值是1 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0] 当前的值是2 [1, 1, 1, 0, 0, 0, 0, 0, 0, 0] 当前的值是3 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0] 当前的值是4 [1, 1, 1, 1, 1, 0, 0, 0, 0, 0] 当前的值是5 [1, 1, 1, 1, 1, 1, 0, 0, 0, 0] 当前的值是6 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0] 当前的值是7 [1, 1, 1, 1, 1, 1, 1, 1, 0, 0] 当前的值是8 [1, 1, 1, 1, 1, 1, 1, 1, 1, 0] 当前的值是9 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 进程已结束,退出代码0
2、程序加锁:
1 import threading 2 import random 3 import time 4 5 lock = threading.Lock() 6 7 list1 = [0] * 10 # [0,0,0,0,0,0,0,0,0,0] 8 9 10 def task1(): 11 lock.acquire() # 请求得到锁 12 for i in range(len(list1)): 13 list1[i] = 1 # random.randint(1, 100) 14 time.sleep(0.5) 15 print(list1) 16 lock.release() # 释放锁 17 18 19 def task2(): 20 # 获取线程锁,如果已经上锁,则等待锁的释放 21 lock.acquire() 22 for i in range(len(list1)): 23 print(f'当前的值是{i}') 24 time.sleep(0.5) 25 lock.release() 26 27 28 if __name__ == '__main__': 29 t1 = threading.Thread(target=task1) 30 t2 = threading.Thread(target=task2) 31 32 t1.start() 33 t2.start()
运行结果:
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0] [1, 1, 0, 0, 0, 0, 0, 0, 0, 0] [1, 1, 1, 0, 0, 0, 0, 0, 0, 0] [1, 1, 1, 1, 0, 0, 0, 0, 0, 0] [1, 1, 1, 1, 1, 0, 0, 0, 0, 0] [1, 1, 1, 1, 1, 1, 0, 0, 0, 0] [1, 1, 1, 1, 1, 1, 1, 0, 0, 0] [1, 1, 1, 1, 1, 1, 1, 1, 0, 0] [1, 1, 1, 1, 1, 1, 1, 1, 1, 0] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 当前的值是0 当前的值是1 当前的值是2 当前的值是3 当前的值是4 当前的值是5 当前的值是6 当前的值是7 当前的值是8 当前的值是9 进程已结束,退出代码0
死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。尽管死锁很少发生,但一旦发生就会造成应用的停止响应,程序不做任何事情。 为什么会产生死锁? 1.因为系统资源不足。 2.进程运行推进的顺序不合适。 3.资源分配不当 例如: 死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。 死锁案例:
1 from threading import Thread, Lock 2 import time 3 4 lockA = Lock() 5 lockB = Lock() 6 7 8 class MyThread1(Thread): # 自定义线程 9 def run(self): 10 if lockA.acquire(): 11 print(f"{self.name}获取了A锁....") 12 time.sleep(0.1) 13 14 if lockB.acquire(timeout=5): # 超时自动释放锁,自动调用 release() 15 print(f"{self.name}又获取了B锁,原程序中还有A锁") 16 lockB.release() 17 18 lockA.release() 19 20 21 class MyThread2(Thread): 22 def run(self): 23 if lockB.acquire(): 24 print(f"{self.name}获取了B锁....") 25 time.sleep(0.1) 26 27 if lockA.acquire(timeout=5): # 超时自动释放锁,自动调用 release() 28 print(f"{self.name}又获取了A锁,原程序中还有B锁") 29 lockA.release() 30 31 lockB.release() 32 33 34 if __name__ == '__main__': 35 t1 = MyThread1() 36 t2 = MyThread2() 37 38 t1.start() 39 t2.start()
原运行结果:
解决死锁后的运行结果:
Thread-1获取了A锁.... Thread-2获取了B锁.... Thread-1又获取了B锁,原程序中还有A锁 进程已结束,退出代码0产生死锁的条件有四个: 1.互斥条件:所谓互斥就是进程在某一时间内独占资源。 2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 只要破坏了一个必要条件,那么我们的死锁就解决了 标签:__,同步,Thread,list1,threading,线程,当前 From: https://www.cnblogs.com/dudu-/p/16725042.html