16.2.3. RLock Objects
def RLock(*args, **kwargs):
"""Factory function that returns a new reentrant lock.
A reentrant lock must be released by the thread that acquired it. Once a
thread has acquired a reentrant lock, the same thread may acquire it again
without blocking; the thread must release it once for each time it has
acquired it.
"""
翻译:RLock是一个工厂函数,它返回一个可重入锁。可重入锁只能被所有者释放。一旦一个线程获得了可重入锁,那么它可以再次获取到,而不用阻塞等待;有几次acquire,必须对应几次release。
RLock与Lock的区别:
1、Lock同一时刻只能被上锁一次,而RLock可以被同一所有者上N次锁
2、Lock可以被非所有者释放,而RLock只能被所有者释放
演示:有一个售票系统,一共有5个售票窗口,当前剩余5张票,同时售卖(没有使用锁)
# coding:gbk
import threading
import time
total=5 #总共的票数
def sale():
global total
time.sleep(1)
print ('正在售出第%s张票\n' % total).decode('gbk')
time.sleep(1)
total-=1
if __name__ == '__main__':
threads=[]
for i in range(5): #创建5个线程,代表5个售票窗口
t=threading.Thread(target=sale,args=())
threads.append(t)
for t in threads: #开始售票
t.start()
运行结果:
C:\Python27\python.exe E:/pythonproj/基础练习/t4.py
正在售出第5张票
正在售出第5张票
正在售出第5张票
正在售出第5张票
正在售出第5张票
Process finished with exit code 0
演示:有一个售票系统,一共有5个售票窗口,当前剩余5张票,同时售卖(使用了RLock锁)
# coding:gbk
import threading
import time
total=5 #总共的票数
lock=threading.RLock() #创建可重入互斥锁
def sale():
global total
lock.acquire()
time.sleep(0.5)
print ('正在售出第%s张票\n' % total).decode('gbk')
time.sleep(0.5)
total-=1
lock.release()
if __name__ == '__main__':
threads=[]
for i in range(5): #创建5个线程,代表5个售票窗口
t=threading.Thread(target=sale,args=())
threads.append(t)
for t in threads: #开始售票
t.start()
运行结果:
C:\Python27\python.exe E:/pythonproj/基础练习/t4.py
正在售出第5张票
正在售出第4张票
正在售出第3张票
正在售出第2张票
正在售出第1张票
Process finished with exit code 0
演示:演示RLock锁可重入特性(这里的可重入指的是可以被同一个线程多次加锁)
# coding:gbk
import threading
import time
total=5 #总共的票数
lock=threading.Lock() #创建互斥锁
if __name__ == '__main__':
lock.acquire()
lock.acquire() #程序阻塞在这里
lock.release()
lock.release()
上面的程序运行会导致死锁。而下面的程序使用了RLock,程序不会阻塞。
# coding:gbk
import threading
import time
total=5 #总共的票数
lock=threading.RLock() #创建可重入互斥锁
if __name__ == '__main__':
lock.acquire()
lock.acquire()
lock.release()
lock.release()