溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

在python中如何解決死鎖的問(wèn)題

發(fā)布時(shí)間:2021-04-15 14:32:54 來(lái)源:億速云 閱讀:236 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)在python中如何解決死鎖的問(wèn)題,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

1.添加超時(shí)時(shí)間:

fromthreading import Thread, Lock
importtime 
mutex1= Lock()  # 創(chuàng)建一個(gè)互斥鎖
mutex2= Lock()  # 創(chuàng)建一個(gè)互斥鎖
def fun1():
    while True:
        mutex1.acquire()
        print("線程1 鎖住了mutex1")
        time.sleep(0.1)
 
        result =mutex2.acquire(timeout=1)  # timeout指明acquire等的最長(zhǎng)超時(shí)時(shí)間
        # result = mutex2.acquire(False)  # 非阻塞
        if result:
            # 表示對(duì)mutex2成功上鎖
            print("線程1 鎖住了mutex2")
            print("線程1 hello")
            mutex1.release()
            mutex2.release()
            break
        else:
            # 表示對(duì)mutex2上鎖失敗
           mutex1.release()  # 將mutex1釋放,保證別人能夠執(zhí)行
            time.sleep(0.1)
def fun2():
    mutex2.acquire()
    print("線程2 鎖住了mutex2")
    time.sleep(0.1)
    mutex1.acquire()
    print("線程2 鎖住了mutex1")
    print("線程2 hi") 
    mutex1.release()
    mutex2.release()

2.附錄-銀行家算法( 不要求,理解就可以)

背景知識(shí)

一個(gè)銀行家如何將一定數(shù)目的資金安全地借給若干個(gè)客戶(hù),使這些客戶(hù)既能借到錢(qián)完成要干的事,同時(shí)銀行家又能收回全部資金而不至于破產(chǎn),這就是銀行家問(wèn)題。這個(gè)問(wèn)題同操作系統(tǒng)中資源分配問(wèn)題十分相似:銀行家就像一個(gè)操作系統(tǒng),客戶(hù)就像運(yùn)行的進(jìn)程,銀行家的資金就是系統(tǒng)的資源。

問(wèn)題的描述

一個(gè)銀行家擁有一定數(shù)量的資金,有若干個(gè)客戶(hù)要貸款。每個(gè)客戶(hù)須在一開(kāi)始就聲明他所需貸款的總額。若該客戶(hù)貸款總額不超過(guò)銀行家的資金總數(shù),銀行家可以接收客戶(hù)的要求??蛻?hù)貸款是以每次一個(gè)資金單位(如1萬(wàn)RMB等)的方式進(jìn)行的,客戶(hù)在借滿(mǎn)所需的全部單位款額之前可能會(huì)等待,但銀行家須保證這種等待是有限的,可完成的。

例如:有三個(gè)客戶(hù)C1,C2,C3,向銀行家借款,該銀行家的資金總額為10個(gè)資金單位,其中C1客戶(hù)要借9各資金單位,C2客戶(hù)要借3個(gè)資金單位,C3客戶(hù)要借8個(gè)資金單位,總計(jì)20個(gè)資金單位。某一時(shí)刻的狀態(tài)如圖所示。

在python中如何解決死鎖的問(wèn)題

對(duì)于a圖的狀態(tài),按照安全序列的要求,我們選的第一個(gè)客戶(hù)應(yīng)滿(mǎn)足該客戶(hù)所需的貸款小于等于銀行家當(dāng)前所剩余的錢(qián)款,可以看出只有C2客戶(hù)能被滿(mǎn)足:C2客戶(hù)需1個(gè)資金單位,小銀行家手中的2個(gè)資金單位,于是銀行家把1個(gè)資金單位借給C2客戶(hù),使之完成工作并歸還所借的3個(gè)資金單位的錢(qián),進(jìn)入b圖。同理,銀行家把4個(gè)資金單位借給C3客戶(hù),使其完成工作,在c圖中,只剩一個(gè)客戶(hù)C1,它需7個(gè)資金單位,這時(shí)銀行家有8個(gè)資金單位,所以C1也能順利借到錢(qián)并完成工作。最后(見(jiàn)圖d)銀行家收回全部10個(gè)資金單位,保證不賠本。那麼客戶(hù)序列{C1,C2,C3}就是個(gè)安全序列,按照這個(gè)序列貸款,銀行家才是安全的。否則的話(huà),若在圖b狀態(tài)時(shí),銀行家把手中的4個(gè)資金單位借給了C1,則出現(xiàn)不安全狀態(tài):這時(shí)C1,C3均不能完成工作,而銀行家手中又沒(méi)有錢(qián)了,系統(tǒng)陷入僵持局面,銀行家也不能收回投資。

綜上所述,銀行家算法是從當(dāng)前狀態(tài)出發(fā),逐個(gè)按安全序列檢查各客戶(hù)誰(shuí)能完成其工作,然后假定其完成工作且歸還全部貸款,再進(jìn)而檢查下一個(gè)能完成工作的客戶(hù),......。如果所有客戶(hù)都能完成工作,則找到一個(gè)安全序列,銀行家才是安全的。

補(bǔ)充:python基礎(chǔ)-死鎖、遞歸鎖

死鎖

所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程或線程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱(chēng)系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱(chēng)為死鎖進(jìn)程

from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock()
class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()
    def func1(self):
        mutexA.acquire()
        print('\033[41m%s 拿到A鎖\033[0m' %self.name)
        mutexB.acquire()
        print('\033[42m%s 拿到B鎖\033[0m' %self.name)
        mutexB.release()
        mutexA.release()
    def func2(self):
        mutexB.acquire()
        print('\033[43m%s 拿到B鎖\033[0m' %self.name)
        time.sleep(2)
        mutexA.acquire()
        print('\033[44m%s 拿到A鎖\033[0m' %self.name)
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(5):
        t=MyThread()
        t.start()

輸出如下:

Thread-1 拿到A鎖

Thread-1 拿到B鎖

Thread-1 拿到B鎖

Thread-2 拿到A鎖

分析如上代碼是如何產(chǎn)生死鎖的:

啟動(dòng)5個(gè)線程,執(zhí)行run方法,假如thread1首先搶到了A鎖,此時(shí)thread1沒(méi)有釋放A鎖,緊接著執(zhí)行代碼mutexB.acquire(),搶到了B鎖,在搶B鎖時(shí)候,沒(méi)有其他線程與thread1爭(zhēng)搶?zhuān)驗(yàn)锳鎖沒(méi)有釋放,其他線程只能等待,然后A鎖就執(zhí)行完func1代碼,然后繼續(xù)執(zhí)行func2代碼,與之同時(shí),在func2中,執(zhí)行代碼 mutexB.acquire(),搶到了B鎖,然后進(jìn)入睡眠狀態(tài),在thread1執(zhí)行完func1函數(shù),釋放AB鎖時(shí)候,其他剩余的線程也開(kāi)始搶A鎖,執(zhí)行func1代碼,如果thread2搶到了A鎖,接下來(lái)thread2要搶B鎖,ok,在這個(gè)時(shí)間段,thread1已經(jīng)執(zhí)行func2搶到了B鎖,然后在sleep(2),持有B鎖沒(méi)有釋放,為什么沒(méi)有釋放,因?yàn)闆](méi)有其他的線程與之爭(zhēng)搶?zhuān)荒芩缓髏hread1握著B(niǎo)鎖,thread2要搶B鎖,ok,這樣就形成了死鎖

遞歸鎖

我們分析了死鎖,那么python里面是如何解決這樣的遞歸鎖呢?

在Python中為了支持在同一線程中多次請(qǐng)求同一資源,python提供了可重入鎖RLock。

這個(gè)RLock內(nèi)部維護(hù)著一個(gè)Lock和一個(gè)counter變量,counter記錄了acquire的次數(shù),從而使得資源可以被多次require。直到一個(gè)線程所有的acquire都被release,其他的線程才能獲得資源。上面的例子如果使用RLock代替Lock,則不會(huì)發(fā)生死鎖:

from threading import Thread,Lock,RLock
import time
mutexA=mutexB=RLock()
class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
    def f1(self):
        mutexA.acquire()
        print('%s 拿到A鎖' %self.name)
        mutexB.acquire()
        print('%s 拿到B鎖' %self.name)
        mutexB.release()
        mutexA.release()
    def f2(self):
        mutexB.acquire()
        print('%s 拿到B鎖' % self.name)
        time.sleep(0.1)
        mutexA.acquire()
        print('%s 拿到A鎖' % self.name)
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(5):
        t=MyThread()
        t.start()

輸出代碼如下:

E:\python\python_sdk\python.exe "E:/python/py_pro/3 死鎖現(xiàn)象與遞歸鎖.py"

Thread-1 拿到A鎖

Thread-1 拿到B鎖

Thread-1 拿到B鎖

Thread-1 拿到A鎖

Thread-2 拿到A鎖

Thread-2 拿到B鎖

Thread-2 拿到B鎖

Thread-2 拿到A鎖

Thread-4 拿到A鎖

Thread-4 拿到B鎖

Thread-4 拿到B鎖

Thread-4 拿到A鎖

Thread-3 拿到A鎖

Thread-3 拿到B鎖

Thread-3 拿到B鎖

Thread-3 拿到A鎖

Thread-5 拿到A鎖

Thread-5 拿到B鎖

Thread-5 拿到B鎖

Thread-5 拿到A鎖

Process finished with exit code 0

或者如下的效果:

在python中如何解決死鎖的問(wèn)題

來(lái)解釋下遞歸鎖的代碼:

由于鎖A,B是同一個(gè)遞歸鎖,thread1拿到A,B鎖,counter記錄了acquire的次數(shù)2次,然后在func1執(zhí)行完畢,就釋放遞歸鎖,在thread1釋放完遞歸鎖,執(zhí)行完func1代碼,接下來(lái)會(huì)有2種可能,1、thread1在次搶到遞歸鎖,執(zhí)行func2代碼 2、其他的線程搶到遞歸鎖,去執(zhí)行func1的任務(wù)代碼

關(guān)于“在python中如何解決死鎖的問(wèn)題”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI