Python 并发编程之线程锁

网友投稿 573 2022-05-30

Python 并发编程之线程锁

线程 --> 锁

GIL 是python 解释器全局锁

多个线程抢占资源的情况:

from threading import Thread import os,time def work():     global n     temp=n     time.sleep(0.1)     n=temp-1 if __name__ == '__main__':     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果可能为99

import threading R=threading.Lock() R.acquire() ''' 对公共数据的操作 '''

同步锁的引用:

from threading import Thread,Lock import os,time def work():     global n     lock.acquire()     temp=n     time.sleep(0.1)     n=temp-1     lock.release() if __name__ == '__main__':     lock=Lock()     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全

互斥锁与join的区别:

#不加锁:并发执行,速度快,数据不安全 from threading import current_thread,Thread,Lock import os,time def task():     global n     print('%s is running' %current_thread().getName())     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:0.5216062068939209 n:99 ''' #不加锁:未加锁部分并发执行,加锁部分串行执行,速度慢,数据安全 from threading import current_thread,Thread,Lock import os,time def task():     #未加锁的代码并发运行     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     #加锁的代码串行运行     lock.acquire()     temp=n     time.sleep(0.5)     n=temp-1     lock.release() if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:53.294203758239746 n:0 ''' #有的同学可能有疑问:既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊 #没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是 #start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的 #单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高. from threading import current_thread,Thread,Lock import os,time def task():     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     start_time=time.time()     for i in range(100):         t=Thread(target=task)         t.start()         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 start to run Thread-2 start to run ...... Thread-100 start to run 主:350.6937336921692 n:0 #耗时是多么的恐怖 '''

进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额

所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

死锁:

from threading import Lock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()

解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

递归锁:

from threading import RLock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()

典型问题:科学家吃面

死锁问题:

import time from threading import Thread,Lock noodle_lock = Lock() fork_lock = Lock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()

递归锁解决死锁问题:

import time from threading import Thread,RLock fork_lock = noodle_lock = RLock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()

软件开发 人工智能 云计算 机器学习

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:[HTTP][会话与消息][三][学习笔记]
下一篇:华为智能制造云、软件开发云——助力沈阳企业产业转型升级
相关文章