python线程锁

**锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:

一个小的案例

import threading

R=threading.Lock()

R.acquire()
'''
对公共数据的操作
'''
R.release()
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,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全

死锁现象与递归锁

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

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

from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock()

class MyThread(Thread):
 def run(self):
 self.func1()
 self.func2()
 def func1(self):
 mutexA.acquire()
 print('\033[41m%s 拿到A锁\033[0m' %self.name)

mutexB.acquire()
 print('\033[42m%s 拿到B锁\033[0m' %self.name)
 mutexB.release()

mutexA.release()

def func2(self):
 mutexB.acquire()
 print('\033[43m%s 拿到B锁\033[0m' %self.name)
 time.sleep(2)

mutexA.acquire()
 print('\033[44m%s 拿到A锁\033[0m' %self.name)
 mutexA.release()

mutexB.release()

if __name__ == '__main__':
 for i in range(10):
 t=MyThread()
 t.start()

'''
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁
然后就卡住,死锁了
'''

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

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

mutexA=mutexB=threading.RLock() #一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止

python线程锁
http://www.jcwit.com/article/106/
作者
Carlos
发布于
2018年6月18日
许可协议