python网络编程之死锁与递归锁、信号量(三)

python之死锁与递归锁

说到递归锁就要先说到死锁,下面给出死锁的定义:
在线程间共享多个资源的时候,如果俩个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,因为系统判断这部分资源正在使用,所以这俩线程在无外力作用下将一直等待下去。

死锁代码示例:

import threading
import time


class MyThread(threading.Thread):
    def actionA(self):
        A.acquire()
        print(self.name,'gotA',time.ctime())
        time.sleep(2)
        B.acquire()
        print(self.name, 'gotB', time.ctime())
        time.sleep(1)

        B.release()
        A.release()
    def actionB(self):
        B.acquire()
        print(self.name, 'gotB', time.ctime())
        time.sleep(2)
        A.acquire()
        print(self.name, 'gotA', time.ctime())
        time.sleep(1)

        A.release()
        B.release()
    def run(self):
        self.actionA()
        self.actionB()

if __name__ == '__main__':
    A = threading.Lock()
    B = threading.Lock()
    L = []

    for i in range(5):
        t = MyThread()
        t.start()
        L.append(t)

    for i in L:
        i.join()

    print('over........')

运行结果:
Thread-1 gotA Tue Aug 21 16:45:50 2018
Thread-1 gotB Tue Aug 21 16:45:52 2018
Thread-1 gotB Tue Aug 21 16:45:53 2018
Thread-2 gotA Tue Aug 21 16:45:53 2018
结果会卡在这儿,原因就是第一个线程执行完actionA后开始执行actionB,而第二个开始执行actionA,它们会对锁产生抢占,所以导致运行卡住形成死锁现象。

递归锁

针对threading.Lock()出现死锁现象,用到了递归锁threading.RLock()
特点:可以连续acquire()

递归锁代码改写:

import threading
import time


class MyThread(threading.Thread):
    def actionA(self):
        r_lock.acquire()
        print(self.name,'gotA',time.ctime())
        time.sleep(2)
        r_lock.acquire()
        print(self.name, 'gotB', time.ctime())
        time.sleep(1)

        r_lock.release()
        r_lock.release()
    def actionB(self):
        r_lock.acquire()
        print(self.name, 'gotB', time.ctime())
        time.sleep(2)
        r_lock.acquire()
        print(self.name, 'gotA', time.ctime())
        time.sleep(1)

        r_lock.release()
        r_lock.release()
    def run(self):
        self.actionA()
        self.actionB()

if __name__ == '__main__':
    # A = threading.Lock()
    # B = threading.Lock()
    r_lock = threading.RLock()

    L = []

    for i in range(5):
        t = MyThread()
        t.start()
        L.append(t)

    for i in L:
        i.join()

    print('over........')

运行结果:
Thread-1 gotA Tue Aug 21 17:10:43 2018
Thread-1 gotB Tue Aug 21 17:10:45 2018
Thread-2 gotA Tue Aug 21 17:10:46 2018
Thread-2 gotB Tue Aug 21 17:10:48 2018
Thread-2 gotB Tue Aug 21 17:10:49 2018
Thread-2 gotA Tue Aug 21 17:10:51 2018
Thread-4 gotA Tue Aug 21 17:10:52 2018
Thread-4 gotB Tue Aug 21 17:10:54 2018
Thread-5 gotA Tue Aug 21 17:10:55 2018
Thread-5 gotB Tue Aug 21 17:10:57 2018
Thread-5 gotB Tue Aug 21 17:10:58 2018
Thread-5 gotA Tue Aug 21 17:11:00 2018
Thread-3 gotA Tue Aug 21 17:11:01 2018
Thread-3 gotB Tue Aug 21 17:11:03 2018
Thread-3 gotB Tue Aug 21 17:11:04 2018
Thread-3 gotA Tue Aug 21 17:11:06 2018
Thread-1 gotB Tue Aug 21 17:11:07 2018
Thread-1 gotA Tue Aug 21 17:11:09 2018
Thread-4 gotB Tue Aug 21 17:11:10 2018
Thread-4 gotA Tue Aug 21 17:11:12 2018
over……..

递归锁的实质上RLock内部加了个计数器,获取一次acquire计数器就加个1,释放一次就减1,当计数器为0时,其他线程可以执行。

信号量(Semaphore)

信号量:
是用来控制线程并发数的,BoundeSemaphore 或Semaphore管理一个内置的计数器,每当调用acquire()时减一,调用release()时加一。计数器不能小于0,当计数器为0时,acquire将阻塞线程至同步锁定状态,直到其他线程调用release().(类似于停车位的概念)

BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release时检查计数器的值是否超过计数器的初始值,如果超过了将抛出一个异常。

信号量代码示例:

  import threading
import time
class myThread(threading.Thread):
    def run(self):
        if semaphore.acquire():
            print(self.name)
            time.sleep(5)
            semaphore.release()

if __name__ == '__main__':
    semaphore = threading.Semaphore(5)
    thrs = []
    for i in range(100):
        thrs.append(myThread())
    for t in thrs:
        t.start()           

运行结果是5次5次出现,每次停顿5秒。

猜你喜欢

转载自blog.csdn.net/huang_yong_peng/article/details/81911338