python多線程編程4: 死結和可重新進入鎖

來源:互聯網
上載者:User
死結

線上程間共用多個資源的時候,如果兩個線程分別佔有一部分資源並且同時等待對方的資源,就會造成死結。儘管死結很少發生,但一旦發生就會造成應用的停止回應。下面看一個死結的例子:

# encoding: UTF-8import threadingimport time  class MyThread(threading.Thread):    def do1(self):        global resA, resB        if mutexA.acquire():             msg = self.name+' got resA'             print msg                            if mutexB.acquire(1):                 msg = self.name+' got resB'                 print msg                 mutexB.release()             mutexA.release()    def do2(self):        global resA, resB        if mutexB.acquire():             msg = self.name+' got resB'             print msg                            if mutexA.acquire(1):                 msg = self.name+' got resA'                 print msg                 mutexA.release()             mutexB.release()             def run(self):        self.do1()        self.do2()resA = 0resB = 0  mutexA = threading.Lock()mutexB = threading.Lock()  def test():    for i in range(5):        t = MyThread()        t.start()if __name__ == '__main__':    test()

執行結果:


Thread-1 got resA

Thread-1 got resB

Thread-1 got resB

Thread-1 got resA

Thread-2 got resA

Thread-2 got resB

Thread-2 got resB

Thread-2 got resA

Thread-3 got resA

Thread-3 got resB

Thread-3 got resB

Thread-3 got resA

Thread-5 got resA

Thread-5 got resB

Thread-5 got resB

Thread-4 got resA


此時進程已經死掉。


可重新進入鎖

更簡單的死結情況是一個線程“迭代”請求同一個資源,直接就會造成死結:

import threadingimport time  class MyThread(threading.Thread):    def run(self):        global num        time.sleep(1)          if mutex.acquire(1):             num = num+1            msg = self.name+' set num to '+str(num)            print msg            mutex.acquire()            mutex.release()            mutex.release()num = 0mutex = threading.Lock()def test():    for i in range(5):        t = MyThread()        t.start()if __name__ == '__main__':    test()

為了支援在同一線程中多次請求同一資源,python提供了“可重新進入鎖”:threading.RLock。RLock內部維護著一個Lock和一個counter變數,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上面的例子如果使用RLock代替Lock,則不會發生死結:

import threadingimport time  class MyThread(threading.Thread):    def run(self):        global num        time.sleep(1)          if mutex.acquire(1):             num = num+1            msg = self.name+' set num to '+str(num)            print msg            mutex.acquire()            mutex.release()            mutex.release()num = 0mutex = threading.RLock()def test():    for i in range(5):        t = MyThread()        t.start()if __name__ == '__main__':    test()

執行結果:


Thread-1 set num to 1

Thread-3 set num to 2

Thread-2 set num to 3

Thread-5 set num to 4

Thread-4 set num to 5

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.