<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [toc] # **進程間同步控制**模塊 鎖 :互斥鎖Lock 數據的安全性問題 進程之間的 信號量 : Semaphore 鎖+計數器 事件 :通過一個flag來控制進程的阻塞和執行 ## 鎖(Lock)的用途 加鎖可以保證多個進程修改同一塊數據時,同一時間只能有一個任務可以進行修改,即串行地修改,沒錯,速度是慢了,但犧牲了速度卻保證了數據安全。 ### 互斥鎖的原理 互斥鎖的意思就是互相排斥,如果把多個進程比喻為多個人,互斥鎖的工作原理就是多個人都要去爭搶同一個資源:衛生間,一個人搶到衛生間后上一把鎖,其他人都要等著,等到這個完成任務后釋放鎖,其他人才有可能有一個搶到...... **互斥鎖的原理,就是把并發改成穿行,降低了效率,但保證了數據安全不錯亂** ### 語法和方法 Lock屬于multiprocessing模塊,常用的方法如下 ~~~ from multiprocessing import Process,Lock #導入 lock.acquire() #加鎖 lock.release() #釋放鎖 ~~~ ### 模擬搶票練習 多個進程共享同一文件,我們可以把文件當數據庫,用多個進程模擬多個人執行搶票任務 ~~~ #文件db.txt的內容為:{"count":1} from multiprocessing import Process import time,json def search(name): dic=json.load(open('db.txt')) time.sleep(1) print('\033[43m%s 查到剩余票數%s\033[0m' %(name,dic['count'])) def get(name): dic=json.load(open('db.txt')) time.sleep(1) #模擬讀數據的網絡延遲 if dic['count'] >0: dic['count']-=1 time.sleep(1) #模擬寫數據的網絡延遲 json.dump(dic,open('db.txt','w')) print('\033[46m%s 購票成功\033[0m' %name) def task(name): search(name) get(name) if __name__ == '__main__': for i in range(4): #模擬并發4個客戶端搶票 name='<路人%s>' %i p=Process(target=task,args=(name,)) p.start() ~~~ 并發運行,效率高,但競爭寫同一文件,數據寫入錯亂,只有一張票,賣成功給了4個人 ~~~ <路人0> 查到剩余票數1 <路人1> 查到剩余票數1 <路人2> 查到剩余票數1 <路人3> 查到剩余票數1 <路人0> 購票成功 <路人1> 購票成功 <路人7> 購票成功 <路人2> 購票成功 ~~~ 加鎖處理:購票行為由并發變成了串行,犧牲了運行效率,但保證了數據安全 ~~~ #把文件db.txt的內容重置為:{"count":1} from multiprocessing import Process,Lock import time,json def search(name): dic=json.load(open('db.txt')) time.sleep(1) print('\033[43m%s 查到剩余票數%s\033[0m' %(name,dic['count'])) def get(name): dic=json.load(open('db.txt')) time.sleep(1) #模擬讀數據的網絡延遲 if dic['count'] >0: dic['count']-=1 time.sleep(1) #模擬寫數據的網絡延遲 json.dump(dic,open('db.txt','w')) print('\033[46m%s 購票成功\033[0m' %name) def task(name,lock): search(name) with lock: #相當于lock.acquire(),執行完自代碼塊自動執行lock.release() get(name) if __name__ == '__main__': lock=Lock() for i in range(4): #模擬并發4個客戶端搶票 name='<路人%s>' %i p=Process(target=task,args=(name,lock)) p.start() ~~~ 執行結果 ~~~ <路人0> 查到剩余票數1 <路人1> 查到剩余票數1 <路人2> 查到剩余票數1 <路人3> 查到剩余票數1 <路人0> 購票成功 ~~~ ### 互斥鎖與join 使用join可以將并發變成串行,互斥鎖的原理也是將并發變成穿行,那我們直接使用join就可以了啊,為何還要互斥鎖. join是將一個任務整體串行,而互斥鎖的好處則是可以將一個任務中的某一段代碼串行,比如只讓task函數中的get任務串行 ~~~ def task(name,): search(name) # 并發執行 lock.acquire() get(name) #串行執行 lock.release() ~~~ ## 信號量(Semaphore) 信號量是對鎖的封裝,鎖是同一時間只能有一個進程可以使用,信號量是同一個之間可以有指定數量的進程可以使用,簡單理解就是鎖+計數器實現的 ~~~ Semaphore管理一個內置的計數器, 每當調用acquire()時內置計數器-1; 調用release() 時內置計數器+1; 計數器不能小于0;當計數器為0時,acquire()將阻塞線程直到其他線程調用release()。 ~~~ ### 信號量的使用 信號量的使用和鎖基本完全一樣,因此直接用下面的爭搶KTV的代碼來演示 ~~~ from multiprocessing import Process from multiprocessing import Semaphore import time,random def ktv(i,sm): sm.acquire() print('%s來了KTV'%i) time.sleep(random.randint(1,3)) print('>>%s唱完了'%i) sm.release() if __name__=='__main__': sm=Semaphore(2) l=[] for i in range(4): p=Process(target=ktv,args=(i,sm)) l.append(p) for p in l: p.start() print('end......') ~~~ 執行結果 ``` 0來了KTV 1來了KTV >>0唱完了 2來了KTV >>1唱完了 3來了KTV >>2唱完了 >>3唱完了 ``` ## 事件(Event) 默認進程之間是不能直接通向的,而如果程序中的其他進程程需要通過判斷某個進程的狀態來確定自己下一步的操作,就需要使用threading庫中的Event(事件)對象。 事件對象包含一個可設置的信號標志,它允許進程等待某些事件的發生。 初始情況下,Event對象中的信號標志被設置為假。如果有線程等待一個Event對象, 而這個Event對象的標志為假,那么這個線程將會被一直阻塞直至該標志為真。一個線程如果將一個Event對象的信號標志設置為真,它將喚醒所有等待這個Event對象的線程。如果一個線程等待一個已經被設置為真的Event對象,那么它將忽略這個事件, 繼續執行 ~~~ from threading import Event event.isSet():返回event的狀態值; event.wait():如果 event.isSet()==False將阻塞線程; event.set(): 設置event的狀態值為True #所有阻塞池的線程激活進入就緒狀態, 等待操作系統調度; event.clear():恢復event的狀態值為False。 ~~~ ### 紅綠燈模型演示 紅綠燈是一個典型的需要用到事件的模型,紅燈和綠燈需要交替的閃爍,而汽車只有當綠燈時才能通過,如果遇到紅燈,需要等待紅燈變為綠燈 ~~~ from multiprocessing import Process from multiprocessing import Event import time,random def traffic_ligths(ev): print('當前是紅燈', ev.is_set()) while True: time.sleep(2) if ev.is_set(): print('綠燈-->紅燈') ev.clear() else: print('紅燈-->綠燈') ev.set() def car(ev,i): if not ev.is_set(): print('卡車%s準備通過'%i) ev.wait() print('卡車%s通過'%i) if __name__=='__main__': ev=Event() p1=Process(target=traffic_ligths,args=(ev,)) p1.daemon p1.start() for i in range(5): p2=Process(target=car,args=(ev,i)) p2.start() time.sleep(random.randrange(0,5)) ~~~ 執行結果: ``` 當前是紅燈 False 卡車0準備通過 紅燈-->綠燈 卡車0通過 綠燈-->紅燈 卡車1準備通過 卡車2準備通過 紅燈-->綠燈 卡車2通過 卡車1通過 卡車3通過 卡車4通過 綠燈-->紅燈 ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看