这是我看到使用的一个例子:
有用的时候
>你想要从类外部进行线程访问,并从类中使用相同的方法:
class X:
def __init__(self):
self.a = 1
self.b = 2
self.lock = threading.RLock()
def changeA(self):
with self.lock:
self.a = self.a + 1
def changeB(self):
with self.lock:
self.b = self.b + self.a
def changeAandB(self):
# you can use chanceA and changeB threadsave!
with self.lock:
self.changeA() # a usual lock would block in here
self.changeB()
>递归更明显:
lock = threading.RLock()
def a(...):
with lock:
a(...) # somewhere inside
其他线程必须等到第一次调用完成=线程所有权。
性能
通常我用Lock开始编程,当情况1或2出现时,我切换到RLock。由于附加的代码,RLock应该稍慢一些。它使用锁:
Lock = _allocate_lock # line 98 threading.py
def RLock(*args, **kwargs):
return _RLock(*args, **kwargs)
class _RLock(_Verbose):
def __init__(self, verbose=None):
_Verbose.__init__(self, verbose)
self.__block = _allocate_lock()
线程所有权
在给定的线程中,您可以随时获取RLock。其他线程需要等到这个线程再次释放资源。
这与Lock有所不同,这意味着“函数调用所有权”(我将这样称呼):另一个函数调用必须等到资源被最后一个阻塞函数释放,即使它在同一个线程中=即使它被另一个函数调用。
何时使用Lock而不是RLock
当您拨打无法控制的资源外部时,
下面的代码有两个变量:a和b,RLock用于确定一个== b * 2
import threading
a = 0
b = 0
lock = threading.RLock()
def changeAandB():
# this function works with an RLock and Lock
with lock:
global a, b
a += 1
b += 2
return a, b
def changeAandB2(callback):
# this function can return wrong results with RLock and can block with Lock
with lock:
global a, b
a += 1
callback() # this callback gets a wrong value when calling changeAandB2
b += 2
return a, b
在changeAandB2中,Lock将是正确的选择,尽管它阻止。或者可以使用RLock._is_owned()来增加错误。当您实现了Observer模式或Publisher-Subscriber并且之后添加锁定时,可能会发生像changeAandB2这样的功能。