• day31 死锁现象、递归锁以及信号量


    死锁现象

    死锁:指的是某个资源被占用后一直得不到释放,导致其他需要这个资源的线程或进程进入阻塞状态

    情况一:对同一把互斥锁多次执行acquire方法,将导致死锁

    from threading import Lock
    
    l = Lock()
    l.acquire()  
    print('run....')  # 打印run....
    l.acquire()
    print('deadlock....')  # 出现死锁,不打印
    

    解决方法:首先这样写没有意义,其次在加锁时加上超时l.acquire(timeout=10),超出时间后继续执行,线程不会卡死

    情况二:一个共享资源要访问必须同时具备多把锁,但是这些锁被不同线程或进程所持有,就会导致线程或进程之间相互等待对方释放,从而导致进入阻塞状态

    import time
    from threading import Lock, Thread
    
    A = Lock()
    B = Lock()
    
    
    class Mytask(Thread):
        def run(self):
            self.eat()
            self.sleep()
    
        def eat(self):
            A.acquire()
            time.sleep(1)
            print(f'{self.name} got A', time.ctime())
            B.acquire()
            print(f'{self.name} got B', time.ctime())
            B.release()
            A.release()
    
        def sleep(self):
            B.acquire()
            time.sleep(1)
            print(f'{self.name} got B', time.ctime())
            A.acquire()
            print(f'{self.name} got A', time.ctime())
            A.release()
            B.release()
    
    
    for i in range(10):
        t = Mytask()
        t.start()
    --------------------------------------------------------------------------
    Thread-1 got A Sat Jul  6 20:37:47 2019
    Thread-1 got B Sat Jul  6 20:37:47 2019
    Thread-2 got A Sat Jul  6 20:37:48 2019  
    Thread-1 got B Sat Jul  6 20:37:48 2019   
    # 线程2抢到了A锁没抢到B锁,线程1抢到了B锁没抢到A锁。线程2等线程1释放B锁,线程1等线程2释放A锁,双方互相等待,造成死锁现象
    

    解决方法:1.抢锁一定按照相同的顺序去抢,2.给抢锁加上超时,如果超时则放弃执行

    递归锁

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

    import time
    from threading import RLock, Thread
    
    R = RLock()
    
    
    class Mytask(Thread):
        def run(self):
            self.eat()
            self.sleep()
    
        def eat(self):
            R.acquire()
            time.sleep(1)
            print(f'{self.name} got A', time.ctime())
            R.release()
    
        def sleep(self):
            R.acquire()
            time.sleep(1)
            print(f'{self.name} got B', time.ctime())
            R.release()
    
    for i in range(10):
        t = Mytask()
        t.start()
    

    与互斥锁的区别:多线程之间都有互斥的效果,不同在于递归锁可以对这个锁执行多次acquire

    信号量

    可以限制同时并发执行公共代码的线程数量,如果限制数量为1则与普通互斥锁没有区别。并不能用来解决安全问题,而是用来限制最大的并发量

    from threading import Semaphore, currentThread, Thread
    
    
    def task():
        s.acquire()
        print('hello world')
        time.sleep(2)
        s.release()
    
    
    s = Semaphore(3)  # 限制线程的并发数,不设置默认为1
    for i in range(10):
        t = Thread(target=task)
        t.start()
    
  • 相关阅读:
    HDU 2013(递归)
    紫书搜索 习题7-6 UVA
    紫书搜索 习题7-4 UVA
    紫书搜索 习题7-3 UVA
    紫书搜索 习题7-2 UVA
    紫书搜索 习题7-1 UVA
    紫书搜索 例题7-10 UVA
    紫书搜索 例题7-13 UVA
    紫书搜索 例题7-12 UVA
    紫书搜索 例题7-9 UVA
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11144120.html
Copyright © 2020-2023  润新知