可重复锁(Reentrant Lock),有人也之为递归锁,不过递归锁这个名字有点狭义。python多线程可重入锁就是threading.RLock对象。
可重入锁的使用场景:
可重入锁与一般的互斥锁一样,都是用来同步线程对共享资源的访问。不过有的时候,同一个线程在获取锁之后,还有可能再次去获取相同的锁。这可能是代码内有递归,也可能是用一把锁保护了好几个不同的共享资源,而这些不同的共享资源可以分别乱序获取。可重入锁在这时就可能发挥作用,它允许线程多次获取同一把锁。这样做事为了防止死锁的放生,如果是普通的Lock,同一个线程在第2次获取时,就死锁了。
可重入锁在使用的时候,要注意申请和释放锁的动作要对称。
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire():
mutex.acquire()
num += 1
msg = self.name+' set num to '+str(num)
print(msg)
mutex.release()
mutex.release()
num = 0
mutex = threading.RLock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
以上代码,每个线程都连续acquire了两次锁,最后也是释放了两次锁!如果不同RLock,而是使用普通的Lock,这段代码就死锁了。运行结果如下:
D:\py>python rlock.py
Thread-5 set num to 1
Thread-3 set num to 2
Thread-1 set num to 3
Thread-4 set num to 4
Thread-2 set num to 5
python官方有关于RLock有一段说明:
A reentrant lock is a synchronization primitive that may be acquired multiple times by the same thread. Internally, it uses the concepts of “owning thread” and “recursion level” in addition to the locked/unlocked state used by primitive locks. In the locked state, some thread owns the lock; in the unlocked state, no thread owns it. To lock the lock, a thread calls its acquire() method; this returns once the thread owns the lock. To unlock the lock, a thread calls its release() method. acquire()/release() call pairs may be nested; only the final release() (the release() of the outermost pair) resets the lock to unlocked and allows another thread blocked in acquire() to proceed.
注意可重入锁对应的owning thread和recursion level这两个概念。
-- EOF --