<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Python中死鎖的形成示例及死鎖情況的防止

        來源:懂視網 責編:小采 時間:2020-11-27 14:29:22
        文檔

        Python中死鎖的形成示例及死鎖情況的防止

        Python中死鎖的形成示例及死鎖情況的防止:死鎖示例 搞多線程的經常會遇到死鎖的問題,學習操作系統的時候會講到死鎖相關的東西,我們用Python直觀的演示一下。 死鎖的一個原因是互斥鎖。假設銀行系統中,用戶a試圖轉賬100塊給用戶b,與此同時用戶b試圖轉賬200塊給用戶a,則可能產生死鎖。 2個線程互
        推薦度:
        導讀Python中死鎖的形成示例及死鎖情況的防止:死鎖示例 搞多線程的經常會遇到死鎖的問題,學習操作系統的時候會講到死鎖相關的東西,我們用Python直觀的演示一下。 死鎖的一個原因是互斥鎖。假設銀行系統中,用戶a試圖轉賬100塊給用戶b,與此同時用戶b試圖轉賬200塊給用戶a,則可能產生死鎖。 2個線程互

        死鎖示例
        搞多線程的經常會遇到死鎖的問題,學習操作系統的時候會講到死鎖相關的東西,我們用Python直觀的演示一下。
        死鎖的一個原因是互斥鎖。假設銀行系統中,用戶a試圖轉賬100塊給用戶b,與此同時用戶b試圖轉賬200塊給用戶a,則可能產生死鎖。
        2個線程互相等待對方的鎖,互相占用著資源不釋放。

        #coding=utf-8 
        import time 
        import threading 
        class Account: 
         def __init__(self, _id, balance, lock): 
         self.id = _id 
         self.balance = balance 
         self.lock = lock 
         
         def withdraw(self, amount): 
         self.balance -= amount 
         
         def deposit(self, amount): 
         self.balance += amount 
         
         
        def transfer(_from, to, amount): 
         if _from.lock.acquire():#鎖住自己的賬戶 
         _from.withdraw(amount) 
         time.sleep(1)#讓交易時間變長,2個交易線程時間上重疊,有足夠時間來產生死鎖 
         print 'wait for lock...' 
         if to.lock.acquire():#鎖住對方的賬戶 
         to.deposit(amount) 
         to.lock.release() 
         _from.lock.release() 
         print 'finish...' 
         
        a = Account('a',1000, threading.Lock()) 
        b = Account('b',1000, threading.Lock()) 
        threading.Thread(target = transfer, args = (a, b, 100)).start() 
        threading.Thread(target = transfer, args = (b, a, 200)).start() 
        
        

        防止死鎖的加鎖機制
        問題:
        你正在寫一個多線程程序,其中線程需要一次獲取多個鎖,此時如何避免死鎖問題。
        解決方案:
        在多線程程序中,死鎖問題很大一部分是由于線程同時獲取多個鎖造成的。舉個例子:一個線程獲取了第一個鎖,然后在獲取第二個鎖的 時候發生阻塞,那么這個線程就可能阻塞其他線程的執行,從而導致整個程序假死。 解決死鎖問題的一種方案是為程序中的每一個鎖分配一個唯一的id,然后只允許按照升序規則來使用多個鎖,這個規則使用上下文管理器 是非常容易實現的,示例如下:

        import threading
        from contextlib import contextmanager
        
        # Thread-local state to stored information on locks already acquired
        _local = threading.local()
        
        @contextmanager
        def acquire(*locks):
         # Sort locks by object identifier
         locks = sorted(locks, key=lambda x: id(x))
        
         # Make sure lock order of previously acquired locks is not violated
         acquired = getattr(_local,'acquired',[])
         if acquired and max(id(lock) for lock in acquired) >= id(locks[0]):
         raise RuntimeError('Lock Order Violation')
        
         # Acquire all of the locks
         acquired.extend(locks)
         _local.acquired = acquired
        
         try:
         for lock in locks:
         lock.acquire()
         yield
         finally:
         # Release locks in reverse order of acquisition
         for lock in reversed(locks):
         lock.release()
         del acquired[-len(locks):]
        
        

        如何使用這個上下文管理器呢?你可以按照正常途徑創建一個鎖對象,但不論是單個鎖還是多個鎖中都使用 acquire() 函數來申請鎖, 示例如下:

        import threading
        x_lock = threading.Lock()
        y_lock = threading.Lock()
        
        def thread_1():
         while True:
         with acquire(x_lock, y_lock):
         print('Thread-1')
        
        def thread_2():
         while True:
         with acquire(y_lock, x_lock):
         print('Thread-2')
        
        t1 = threading.Thread(target=thread_1)
        t1.daemon = True
        t1.start()
        
        t2 = threading.Thread(target=thread_2)
        t2.daemon = True
        t2.start()
        
        

        如果你執行這段代碼,你會發現它即使在不同的函數中以不同的順序獲取鎖也沒有發生死鎖。 其關鍵在于,在第一段代碼中,我們對這些鎖進行了排序。通過排序,使得不管用戶以什么樣的順序來請求鎖,這些鎖都會按照固定的順序被獲取。 如果有多個 acquire() 操作被嵌套調用,可以通過線程本地存儲(TLS)來檢測潛在的死鎖問題。 假設你的代碼是這樣寫的:

        import threading
        x_lock = threading.Lock()
        y_lock = threading.Lock()
        
        def thread_1():
        
         while True:
         with acquire(x_lock):
         with acquire(y_lock):
         print('Thread-1')
        
        def thread_2():
         while True:
         with acquire(y_lock):
         with acquire(x_lock):
         print('Thread-2')
        
        t1 = threading.Thread(target=thread_1)
        t1.daemon = True
        t1.start()
        
        t2 = threading.Thread(target=thread_2)
        t2.daemon = True
        t2.start()
        
        

        如果你運行這個版本的代碼,必定會有一個線程發生崩潰,異常信息可能像這樣:

        Exception in thread Thread-1:
        Traceback (most recent call last):
         File "/usr/local/lib/python3.3/threading.py", line 639, in _bootstrap_inner
         self.run()
         File "/usr/local/lib/python3.3/threading.py", line 596, in run
         self._target(*self._args, **self._kwargs)
         File "deadlock.py", line 49, in thread_1
         with acquire(y_lock):
         File "/usr/local/lib/python3.3/contextlib.py", line 48, in __enter__
         return next(self.gen)
         File "deadlock.py", line 15, in acquire
         raise RuntimeError("Lock Order Violation")
        RuntimeError: Lock Order Violation
        >>>
        

        發生崩潰的原因在于,每個線程都記錄著自己已經獲取到的鎖。 acquire() 函數會檢查之前已經獲取的鎖列表, 由于鎖是按照升序排列獲取的,所以函數會認為之前已獲取的鎖的id必定小于新申請到的鎖,這時就會觸發異常。

        討論
        死鎖是每一個多線程程序都會面臨的一個問題(就像它是每一本操作系統課本的共同話題一樣)。根據經驗來講,盡可能保證每一個 線程只能同時保持一個鎖,這樣程序就不會被死鎖問題所困擾。一旦有線程同時申請多個鎖,一切就不可預料了。

        死鎖的檢測與恢復是一個幾乎沒有優雅的解決方案的擴展話題。一個比較常用的死鎖檢測與恢復的方案是引入看門狗計數器。當線程正常 運行的時候會每隔一段時間重置計數器,在沒有發生死鎖的情況下,一切都正常進行。一旦發生死鎖,由于無法重置計數器導致定時器 超時,這時程序會通過重啟自身恢復到正常狀態。

        避免死鎖是另外一種解決死鎖問題的方式,在進程獲取鎖的時候會嚴格按照對象id升序排列獲取,經過數學證明,這樣保證程序不會進入 死鎖狀態。證明就留給讀者作為練習了。避免死鎖的主要思想是,單純地按照對象id遞增的順序加鎖不會產生循環依賴,而循環依賴是 死鎖的一個必要條件,從而避免程序進入死鎖狀態。

        下面以一個關于線程死鎖的經典問題:“哲學家就餐問題”,作為本節最后一個例子。題目是這樣的:五位哲學家圍坐在一張桌子前,每個人 面前有一碗飯和一只筷子。在這里每個哲學家可以看做是一個獨立的線程,而每只筷子可以看做是一個鎖。每個哲學家可以處在靜坐、 思考、吃飯三種狀態中的一個。需要注意的是,每個哲學家吃飯是需要兩只筷子的,這樣問題就來了:如果每個哲學家都拿起自己左邊的筷子, 那么他們五個都只能拿著一只筷子坐在那兒,直到餓死。此時他們就進入了死鎖狀態。 下面是一個簡單的使用死鎖避免機制解決“哲學家就餐問題”的實現:

        import threading
        
        # The philosopher thread
        def philosopher(left, right):
         while True:
         with acquire(left,right):
         print(threading.currentThread(), 'eating')
        
        # The chopsticks (represented by locks)
        NSTICKS = 5
        chopsticks = [threading.Lock() for n in range(NSTICKS)]
        
        # Create all of the philosophers
        for n in range(NSTICKS):
         t = threading.Thread(target=philosopher,
         args=(chopsticks[n],chopsticks[(n+1) % NSTICKS]))
         t.start()
        
        

        最后,要特別注意到,為了避免死鎖,所有的加鎖操作必須使用 acquire() 函數。如果代碼中的某部分繞過acquire 函數直接申請鎖,那么整個死鎖避免機制就不起作用了。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Python中死鎖的形成示例及死鎖情況的防止

        Python中死鎖的形成示例及死鎖情況的防止:死鎖示例 搞多線程的經常會遇到死鎖的問題,學習操作系統的時候會講到死鎖相關的東西,我們用Python直觀的演示一下。 死鎖的一個原因是互斥鎖。假設銀行系統中,用戶a試圖轉賬100塊給用戶b,與此同時用戶b試圖轉賬200塊給用戶a,則可能產生死鎖。 2個線程互
        推薦度:
        標簽: python 線程 死鎖
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 成人电影在线免费观看| 久9热免费精品视频在线观看| 99亚洲乱人伦aⅴ精品| 一区二区三区免费精品视频| 18禁止看的免费污网站| 四虎成人精品在永久免费| 亚洲国产精品乱码一区二区| 国产成人精品亚洲2020| a毛片视频免费观看影院| 日韩电影免费在线| 亚洲最新永久在线观看| 成在线人直播免费视频| 毛片免费视频播放| 四虎影视在线永久免费看黄| 精品久久久久久久久亚洲偷窥女厕| 在线不卡免费视频| 亚洲性猛交xx乱| 国产精成人品日日拍夜夜免费 | 3344在线看片免费| 久久久久亚洲AV无码专区体验| 亚洲人成免费电影| 亚洲精品美女久久久久99| 香蕉97碰碰视频免费| 卡1卡2卡3卡4卡5免费视频| 蜜芽亚洲av无码一区二区三区| 久久综合AV免费观看| 国产亚洲视频在线| 国产精品视_精品国产免费| 亚洲一区无码中文字幕乱码| 84pao国产成视频免费播放| 婷婷久久久亚洲欧洲日产国码AV| 精品一区二区三区免费观看| 亚洲精品国产自在久久| 免费福利资源站在线视频| 国产高清免费观看| 成在线人视频免费视频 | 亚洲AV综合色区无码另类小说 | 看一级毛片免费观看视频| 亚洲日韩aⅴ在线视频| 久久久久久国产a免费观看不卡 | 久视频精品免费观看99|