python多线程3--锁

98 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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()
    

image-20220603231559048.png

于是就形成了上述的情况,线程A在阻塞恢复后想拿锁B但是被线程2拿了导致线程1不动,而线程2也因为1不动而不动(即B锁拿到了释放后才能释放A锁,而B锁也是同理,但两个线程分别占着锁,所以导致AB均不能释放,所以形成了死锁)