python2.7 threading 模块 二 Lock RLock

1.Lock

Lock的概念很简单,就不多解释了

锁有两种状态:被锁(locked)和没有被锁(unlocked)。拥有acquire()和release()两种方法,并且遵循一下的规则:

  • 如果一个锁的状态是unlocked,调用acquire()方法改变它的状态为locked
  • 如果一个锁的状态是locked,acquire()方法将会阻塞,直到另一个线程调用release()方法释放了锁;
  • 如果一个锁的状态是unlocked调用release()会抛出RuntimeError异常;
  • 如果一个锁的状态是locked,调用release()方法改变它的状态为unlocked。

API 所有的操作都是atomically.

  • Lock.acquire([blocking])
  • Lock.release()

    参数 blocking:

  • True(the default):一直阻塞直到锁被realse.

  • False:如果锁被占用,不阻塞立马返回false

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

2.RLock

可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。

有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 下篇博客再写吧~~~

你可能感兴趣的:(python)