Lock的概念很简单,就不多解释了
锁有两种状态:被锁(locked)和没有被锁(unlocked)。拥有acquire()和release()两种方法,并且遵循一下的规则:
API 所有的操作都是atomically.
Lock.release()
参数 blocking:
True(the default):一直阻塞直到锁被realse.
ps:这是python2.7的Lock.acquire(), python3.x的Lock.acquire(blocking=True, timeout=-1)多了一个超时设置。
一个简单的小例子:
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire():
num = num+1
msg = self.name+' set num to '+str(num)
print msg
mutex.release()
num = 0
mutex = threading.Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
运行结果:
Thread-3 set num to 1
Thread-4 set num to 2
Thread-5 set num to 3
Thread-2 set num to 4
Thread-1 set num to 5
可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。
有Lock了为什么还需要RLock呢?可重入锁最大的作用是在需要重复获得锁的情况下(如:递归调用)避免死锁!!!
RLock对象是Lock对象的一个变种,但是它是一种可重入的Lock,其内部维护着一个Lock对象,还有一个计数器。
下面是RLock的acquire()实现。如果调用acquire()的线程是资源的所有者,记录调用acquire()次数的计数器就会加1。如果不是,就将试图去获取锁。线程第一次获得锁时,锁的拥有者将会被保存,同时计数器初始化为1
def acquire(self, blocking=1):
me = _get_ident()
if self.__owner == me:
self.__count = self.__count + 1
...
return 1
rc = self.__block.acquire(blocking)
if rc:
self.__owner = me
self.__count = 1
...
...
return rc
可重入锁(RLock)的release()方法。首先它会去确认调用者是否是锁的拥有者。如果是的话,计数器减1;如果计数器为0,那么锁将会被释放,这时其他线程就可以去获取锁了。
def release(self):
if self.__owner != _get_ident():
raise RuntimeError("cannot release un-acquired lock")
self.__count = count = self.__count - 1
if not count:
self.__owner = None
self.__block.release()
...
...
使用示例:
1.线程安全的访问一个class,且在一个class 中的某个方法类访问了该类的其他方法。
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()
2.递归调用
lock = threading.RLock()
def a(...):
with lock:
a(...) # somewhere inside
还有两个比较常见的重要的Objects: Condition ,Semaphore 下篇博客再写吧~~~