• 线程死锁和递归锁


    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。

    下面是一个死锁的例子:

    #-*-conding:utf-8-*-
    import threading
    import time

    A = threading.Lock()
    B = threading.Lock()

    class TestThread(threading.Thread):

    def runA(self):
    A.acquire()             #2步骤 5个线程其中一个线程肯定会获取A这把锁,另外4个线程必须在这个位置等着A这把锁释放. #15步骤,此时此刻线程获取了A锁
    print(self.name,'get A',time.ctime()) #3步骤 打印了一条信息 #16步骤,打印了一条信息
    time.sleep(2)              #4步骤 睡2秒                                      #17步骤,睡2秒
      
    B.acquire()               #5步骤 Thread-1线程A锁,在没释放的情况下,有获得了一把B锁(也就是说A锁里面套着B锁)     #18步骤,开始获取B锁;这就出问题了,因为B锁这时候是线程1拿着,线程1等着线程2释放A锁才能继续,线程2有等着线程1释放B锁才能继续,走到就相互等着对方释放卡死了(这就叫死锁)
    print(self.name, 'get B', time.ctime()) #6步骤 打印了一条信息
    time.sleep(1)             #7步骤 睡一秒,(上面4个线程还一直在等待)

    B.release()               #8步骤 释放B锁后,上面的4个线程还在等待,因为A锁没释放
    A.release()               #9步骤 释放A这把锁,这时候第Thread-2二个线程开始运行,有开始获取A这把锁


    def runB(self):               #10步骤 此时,Thread-1;线程1继续运行执行runB方.
    B.acquire()               #11步骤,Thread-1 线程1 接着获取到B这把锁,机会同一时候第二个线程获取了A锁,第一个线程获取了B锁
    print(self.name, 'get B', time.ctime()) #12步骤,打印了一个消息
    time.sleep(2) #13步骤,睡2秒

    A.acquire()               #14步骤,线程1有获取A锁,此时A锁已经被线程2获取了;所有线程1走到的时候,需要等待线程2释放A锁后,才能继续往下走
    print(self.name, 'get A', time.ctime())
    time.sleep(1)

    A.release()
    B.release()

    def run(self):
    self.runA()
    self.runB()


    if __name__ == '__main__':
    l = []
    for i in range(5):  #1步骤 开启5个线程
    t = TestThread()
    t.start() #执行run方法
    l.append(t)

    for i in l:
    i.join()

    print('end threading')

    递归锁
    #-*-conding:utf-8-*-
    import threading
    import time
    A = threading.RLock()         #递归锁 (锁里面维护着一个计数器,当获取一把锁计数器加1 当释放一把锁计数器减一,当递归锁计数器为零线程之间就开始竞争)
    class TestThread(threading.Thread):
    def runA(self):
    A.acquire()           #线程1获取A锁 计数器加1
    print(self.name,'get A',time.ctime())
    time.sleep(2)

    A.acquire() #线程1再次获取A 也就是说线程1获取第一次那把锁,线程1再拿过来锁下面的内容(都是一把锁) 计数器在加1 现在是2
    print(self.name, 'get B', time.ctime())
    time.sleep(1)

    A.release()           #释放
    A.release()           #释放 到这现在递归锁全部释放

    def runB(self):
    A.acquire()           #这时候线程1 有想获取递归(线程能否获得,不一定获得,因为还有4个线程等着获取锁),此时还有4个线程也在等待获取锁,这时候这4个线程和当前线程1会开始竞争,如果线程1竞争胜利,就继续运行(其他线程都无法执行任何代码),如果竞争失败,其他的胜利的线程运行(线程1就在此处等着,下一次胜利,就在这开始运行代码),以此类推
    print(self.name, 'get B', time.ctime())
    time.sleep(2)

    A.acquire()
    print(self.name, 'get A', time.ctime())
    time.sleep(1)

    A.release()
    A.release()

    def run(self):
    self.runA()
    self.runB()

    if __name__ == '__main__':
    l = []
    for i in range(5):
    t = TestThread()
    t.start()
    l.append(t)

    for i in l:
    i.join()

    print('end threading')


     
  • 相关阅读:
    微软O365使用教程:如何邀请客户试用
    Using the ForeFront Identity Manager to Configure SharePoint 2010’s User Profile Sync Service
    SharePoint2010文档归档策略
    转发:SP 2010: Find error messages with a Correlation ID token in SharePoint 2010
    用sql server的脚本导入Excel2010或Excel2013格式数据
    sharepoint2010的调查的问题总结
    暑假第一周进度报告
    暑假第四周进度报告
    暑假第三周学习进度报告
    暑假第二周进度报告
  • 原文地址:https://www.cnblogs.com/ajaxa/p/9121349.html
Copyright © 2020-2023  润新知