python网络编程--线程递归锁RLock

一:死锁

  所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程成为死锁进程。多个lock会造成死锁

二:递归锁和线程锁差异

  在threading模块中,定义两种类型的琐:threading.Lock和threading.RLock

  这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。

  而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,

  必须调用n次的release才能真正释放所占用的琐。它们之间有一点细微的区别,通过比较下面两段代码来说明:

  递归锁与普通的互斥锁最大的不同就是,一个锁的对象内部,维护了一个计数器,这个计数器的初始值是0,

  当一个线程acquire一次这个锁时,内部计数器+1,但是,这把锁的计数器一旦大于0,其他的线程是无法拿到这把锁的,只有当前线程可以拿。

  (当前线程acquire一次,计数器+1,release一次计数器-1,所以,当前的线程想要彻底释放掉递归锁,acquire多少次,就要release多少次!!!)

import threading  
lock = threading.Lock() #Lock对象  
lock.acquire()  
lock.acquire()  #产生了死琐。  
lock.release()  

lock.release()  

 

import threading  
rLock = threading.RLock()  #RLock对象  
rLock.acquire()  
rLock.acquire() #在同一线程内,程序不会堵塞。  
rLock.release()  
rLock.release()  

三:递归锁使用例子

import threading,time

 

def run1():

    print("grab the first part data")

    lock.acquire()

    global num

    num +=1

    lock.release()

    return num

def run2():

    print("grab the second part data")

    lock.acquire()

    global  num2

    num2+=1

    lock.release()

    return num2

def run3():

    lock.acquire()

    res = run1()

    print('--------between run1 and run2-----')

    res2 = run2()

    lock.release()

    print(res,res2)

 

 

if __name__ == '__main__':

 

    num,num2 = 0,0

    lock = threading.RLock()

    for i in range(10):

        t = threading.Thread(target=run3)

        t.start()

 

while threading.active_count() != 1:

    print(threading.active_count())

else:

    print('----all threads done---')

    print(num,num2)

 

 四:总结

  

  如果同一个线程需要多次去访问同一个共享资源,这个时候,就可以使用递归锁(RLock)

  递归锁的内部,维护了一个Lock对象和一个counter计数变量,counter记录了acquire的次数,从而使得资源可以被多次require。

  直到一个线程所有的acquire都被release,其他的线程才能获得资源。

  所以说RLock可以完全代替Lock,能用递归锁尽量用递归锁!

posted on 2017-06-22 14:47  shisanjun  阅读(186)  评论(0编辑  收藏  举报

导航