死锁与递归锁

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

from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock()

class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()
    def func1(self):
        mutexA.acquire()
        print('\033[41m%s 拿到A锁\033[0m' %self.name)

        mutexB.acquire()
        print('\033[42m%s 拿到B锁\033[0m' %self.name)
        mutexB.release()

        mutexA.release()

    def func2(self):
        mutexB.acquire()
        print('\033[43m%s 拿到B锁\033[0m' %self.name)
        time.sleep(2)

        mutexA.acquire()
        print('\033[44m%s 拿到A锁\033[0m' %self.name)
        mutexA.release()

        mutexB.release()

if __name__ == '__main__':
    for i in range(10):
        t=MyThread()
        t.start()

'''
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁
然后就卡住,死锁了
'''
死锁

解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

from threading import Thread,Lock,RLock
import time
# mutexA=mutexB=Lock()
mutexA=mutexB=RLock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print('%s 拿到A锁' %self.name)

        mutexB.acquire()
        print('%s 拿到B锁' %self.name)
        mutexB.release()

        mutexA.release()

    def f2(self):
        mutexB.acquire()
        print('%s 拿到B锁' % self.name)
        time.sleep(0.1)
        mutexA.acquire()
        print('%s 拿到A锁' % self.name)
        mutexA.release()

        mutexB.release()


if __name__ == '__main__':
    for i in range(10):
        t=MyThread()
        t.start()
递归锁
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-1 拿到A锁
Thread-2 拿到A锁
Thread-2 拿到B锁
Thread-2 拿到B锁
Thread-2 拿到A锁
Thread-4 拿到A锁
Thread-4 拿到B锁
Thread-4 拿到B锁
Thread-4 拿到A锁
Thread-6 拿到A锁
Thread-6 拿到B锁
Thread-6 拿到B锁
Thread-6 拿到A锁
Thread-8 拿到A锁
Thread-8 拿到B锁
Thread-8 拿到B锁
Thread-8 拿到A锁
Thread-10 拿到A锁
Thread-10 拿到B锁
Thread-10 拿到B锁
Thread-10 拿到A锁
Thread-5 拿到A锁
Thread-5 拿到B锁
Thread-5 拿到B锁
Thread-5 拿到A锁
Thread-9 拿到A锁
Thread-9 拿到B锁
Thread-9 拿到B锁
Thread-9 拿到A锁
#Thread-7 拿到A锁
#Thread-7 拿到B锁
Thread-3 拿到A锁
Thread-3 拿到B锁
Thread-3 拿到B锁
Thread-3 拿到A锁
#Thread-7 拿到B锁
#Thread-7 拿到A锁
结果

在互斥锁中设置锁A等于锁B,第二次acquire就会报错,因为是一个锁。

 

在进程中,需向子进程传递锁对象

from multiprocessing import Process,RLock
import time

class MyThread(Process):
    def __init__(self,mutex):
        super().__init__()
        self.mutex = mutex
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        self.mutex.acquire()
        print('%s 拿到A锁' %self.name)

        self.mutex.acquire()
        print('%s 拿到B锁' %self.name)
        self.mutex.release()

        self.mutex.release()

    def f2(self):
        self.mutex.acquire()
        print('%s 拿到B锁' % self.name)
        time.sleep(0.1)
        self.mutex.acquire()
        print('%s 拿到A锁' % self.name)
        self.mutex.release()

        self.mutex.release()


if __name__ == '__main__':
    mutexA = mutexB = RLock()
    for i in range(10):
        t=MyThread(mutexA)
        t.start()
进程递归锁

 

MyThread-1 拿到A锁
MyThread-1 拿到B锁
MyThread-1 拿到B锁
MyThread-1 拿到A锁
MyThread-2 拿到A锁
MyThread-2 拿到B锁
MyThread-3 拿到A锁
MyThread-3 拿到B锁
MyThread-4 拿到A锁
MyThread-4 拿到B锁
MyThread-5 拿到A锁
MyThread-5 拿到B锁
MyThread-7 拿到A锁
MyThread-7 拿到B锁
MyThread-2 拿到B锁
MyThread-2 拿到A锁
MyThread-3 拿到B锁
MyThread-3 拿到A锁
MyThread-4 拿到B锁
MyThread-4 拿到A锁
MyThread-5 拿到B锁
MyThread-5 拿到A锁
MyThread-7 拿到B锁
MyThread-7 拿到A锁
MyThread-6 拿到A锁
MyThread-6 拿到B锁
MyThread-8 拿到A锁
MyThread-8 拿到B锁
MyThread-9 拿到A锁
MyThread-9 拿到B锁
MyThread-10 拿到A锁
MyThread-10 拿到B锁
MyThread-6 拿到B锁
MyThread-6 拿到A锁
MyThread-8 拿到B锁
MyThread-8 拿到A锁
MyThread-9 拿到B锁
MyThread-9 拿到A锁
MyThread-10 拿到B锁
MyThread-10 拿到A锁
结果
posted @ 2017-12-05 19:46  瓜田月夜  阅读(125)  评论(0)    收藏  举报