首頁 > 後端開發 > Python教學 > python多執行緒程式設計4: 死鎖和可重入鎖

python多執行緒程式設計4: 死鎖和可重入鎖

高洛峰
發布: 2016-10-18 11:31:53
原創
1437 人瀏覽過

死鎖

在執行緒間共享多個資源的時候,如果兩個執行緒分別佔有一部分資源並且同時等待對方的資源,就會造成死鎖。儘管死鎖很少發生,但一旦發生就會造成應用的停止反應。下面看一個死鎖的範例:

# encoding: UTF-8
import threading
import 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 = 0
resB = 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 resTThread-1 got resB got resA

Thread-2 got resB

Thread-2 got resB

Thread-2 got resA

Thread-3 got resA

resA

Thread-5 got resA

Thread-5 got resB

Thread-5 got resB

Thread-4 got resA

Thread-4 got resA

此時進程已經死掉。


可重入鎖

更簡單的死鎖情況是一個執行緒「迭代」請求同一個資源,直接就會造成死鎖:

import threading
import 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 = 0
mutex = 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 threading
import 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 = 0
mutex = 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

-2
-2 set to 3

Thread-5 set num to 4

Thread-4 set num to 5

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板