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

死锁现象

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

状况一:对同一把互斥锁屡次执行acquire方法,将致使死锁多线程

from threading import Lock

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

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

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

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,则不会发生死锁:code

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()
相关文章
相关标签/搜索