91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》
  • 首頁 > 
  • 教程 > 
  • 開發技術 > 
  • Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

發布時間:2020-10-11 20:52:03 來源:腳本之家 閱讀:185 作者:隨風行云 欄目:開發技術

本文實例講述了Python多線程操作之互斥鎖、遞歸鎖、信號量、事件。分享給大家供大家參考,具體如下:

互斥鎖:

  • 為什么要有互斥鎖:由于多線程是并行的,如果某一線程取出了某一個數據將要進行操作,但它還沒有那么快執行完操作,這時候如果另外一個線程也要操作這個數據,那么這個數據可能會因為兩次操作而發生錯誤
import time,threading

x=6
def run1():
  print("run1我拿到了數據:",x)
  print("我現在還不想操作,先睡一下")
  time.sleep(3)
  print("再看一下數據,穩一穩",x)

def run2():
  global x
  print("run2我拿到了數據:", x)

  x=5
  print(x)

t1=threading.Thread(target=run1)
t2=threading.Thread(target=run2)

t1.start()
t2.start()
t1.join()
t2.join()

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

  • 而多線程的互斥鎖機制本質上是:申請一個鎖,A線程拿了鑰匙【acquire】之后,如果B也想拿到鑰匙是不行的,只有等A把鑰匙還回來【release】才行
  • 如何使用互斥鎖:
    1. 定義一個鎖對象:鎖對象=threading.Lock()
    2. 請求鎖:鎖對象.acquire()
    3. 釋放鎖:鎖對象.release()

使用互斥鎖來更改上段代碼

import time,threading

x=6
def run1():
  lock.acquire()
  global x
  print("run1我拿到了數據,x=",x)
  print("我現在還不想操作,先睡一下")
  time.sleep(3)
  print("再看一下數據,穩一穩,x=",x)
  x+=1
  print("run1操作完畢:x=",x)
  lock.release()
def run2():
  lock.acquire()
  global x
  print("run2我拿到了數據:", x)
  x+=1
  print("run2操作完畢:x=",x)
  lock.release()

lock=threading.Lock()#生成一個鎖對象
t1=threading.Thread(target=run1)
t2=threading.Thread(target=run2)

t1.start()
t2.start()
start_time=time.time()
t1.join()
t2.join()
print("最終的x=",x)
print(time.time()-start_time)#3.0多說明,由于受到鎖的影響,run2要等待run1釋放lock,所以變成了串行

這種互斥鎖在操作系統中可以稱作“臨界區”,如果想了解更多:

https://baike.baidu.com/item/%E4%B8%B4%E7%95%8C%E5%8C%BA/8942134?fr=aladdin

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解


遞歸鎖:

  • 為什么要有遞歸鎖:互斥鎖本質上是阻止其他線程進入,如果有兩個需要阻止其他線程進入的操作【像兩個人過獨木橋】,那么需要兩個鎖,而想要鎖上第二個如果直接用第一個鎖的acquire會失敗,因為第一個鎖還沒release,我們可以選擇再定義一個互斥鎖對象來acquire,但這僅僅是兩層的情況下,如果多層的吧,那么就需要定義好幾個互斥鎖對象了【而且由于對象變多,有時候會因為互相調用鎖而發生死鎖】。遞歸鎖就是為了處理這種情況,遞歸鎖對象允許多次acquire和多次release
    • 發生死鎖的情況[A拿到A鎖,想要拿B鎖,B拿著B鎖,想要A鎖]

【以過獨木橋為例】:橋只能容一個人通過,A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人,當他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人,B情況相反:【于是當兩個人一起過橋的時候就會發生死鎖】

import threading,time

"""
A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人,
當他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人
"""
def A():
  lockNorth.acquire()#拿到北邊橋的鎖
  print("A過橋北")
  time.sleep(3)#過橋中
  lockSorth.acquire()#企圖過到南邊橋,
  print("A過橋南")
  time.sleep(3) # 過橋中
  lockSorth.release()
  lockNorth.release()
  print("A過橋成功")

"""
B只能看得到南邊橋上有沒有人,看不到北邊橋有沒有人,
當他看到南邊橋沒人就會過橋,等到他到橋中間才能看到北邊橋有沒有人
"""
def B():
  lockSorth.acquire() # 企圖過到南邊橋,
  print("B過橋南")
  time.sleep(3) # 過橋中
  lockNorth.acquire() # 拿到北邊橋的鎖
  print("B過橋北")
  time.sleep(3) # 過橋中
  lockNorth.release()
  lockSorth.release()
  print("B過橋成功")


lockNorth=threading.Lock()
lockSorth=threading.Lock()

tA=threading.Thread(target=A)
tB=threading.Thread(target=B)
tA.start()
tB.start()

tA.join()
tB.join()

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

  • 遞歸鎖的本質是:本質上還是一個鎖,但如果在一個線程里面可以多次acquire。【因為只有一個鎖,所以不會發生互相調用的死鎖,而因為可以多次調用,所以可以鎖多次】
  • 如何使用遞歸鎖:
    1. 定義一個鎖對象:遞歸鎖對象=threading.RLock()
    2. 請求鎖:鎖對象.acquire()
    3. 釋放鎖:鎖對象.release()

使用遞歸鎖來解決上面的死鎖問題:

import threading,time

"""
A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人,
當他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人
"""
def A():
  lock.acquire()#拿到北邊橋的鎖
  print("A過橋北")
  time.sleep(3)#過橋中
  lock.acquire()#企圖過到南邊橋,
  print("A過橋南")
  time.sleep(3) # 過橋中
  lock.release()
  lock.release()
  print("A過橋成功")

"""
B只能看得到南邊橋上有沒有人,看不到北邊橋有沒有人,
當他看到南邊橋沒人就會過橋,等到他到橋中間才能看到北邊橋有沒有人
"""
def B():
  lock.acquire() # 拿南橋鎖,
  print("B過橋南")
  time.sleep(3) # 過橋中
  lock.acquire() # 企圖拿北橋的鎖
  print("B過橋北")
  time.sleep(3) # 過橋中
  lock.release()
  lock.release()
  print("B過橋成功")


lock=threading.RLock()

tA=threading.Thread(target=A)
tB=threading.Thread(target=B)
tA.start()
tB.start()

tA.join()
tB.join()

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

【由于本質是一把鎖,A拿到鎖后,B要等待】


信號量:

  • 什么是信號量:

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

信號量可以限制進入的線程的數量。

  • 如何使用信號量:
    1. 創建信號量對象:信號量對象=threading.BoundedSemaphore(x),x是限制進程的數量
    2. 當有進程需要進入的時候,調用acquire()來減少信號量:信號量對象.acquire()
    3. 當有進程離開的時候,調用release()來增加信號量:信號量對象.release()
import threading,time


def run():
  s.acquire()
  print("hello")
  time.sleep(1.5)
  s.release()

s=threading.BoundedSemaphore(3)#限制3個

threading_list=[]
for i in range(12):#創建12個線程
  obj=threading.Thread(target=run)
  obj.setDaemon(True) # 設置守護線程,避免干擾主線程運行,并行等待
  obj.start()

for i in range(4):
  print("")#為了把結果分割,可以清楚看出分為了三組
  time.sleep(1.5)
#結果分為三組是因為運行的太快了,三個線程裝入的時間差太小

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解


事件:

  • 什么是事件:當發生線程發生一件事的時候如果要提醒另外一個線程,使用事件。雙方共享該事件對象【等待的一方會阻塞而進行等待】,當一方更改事件對象的時候,另外一方也能知道【以讀者-寫者為例:讀者要等寫者告訴他去讀才會去讀,寫者寫完后要設置一個事件,當該事件設置時,讀者就會來讀】
  • 如何使用事件:
    1. 創建事件對象:事件對象=threading.Event()
    2. 設置事件:事件對象.set()    判斷事件是否set:事件對象.is_set(),等待事件set:事件對象.wait()
    3. 清除事件:事件對象.clear() 
import threading,time


def read():
  while True:
    if event.is_set():
      print("事件已設置,我要讀了!!!!")
      time.sleep(1)
    else:#事件未設置
      print("還沒寫好,我要等咯")
      event.wait()#那么就等著咯
      #如果等到了
      print("終于等到了!那么我又可以讀了")
      time.sleep(1)

def write():
  event.clear()#初始設空
  while True:
    time.sleep(3)#寫
    event.set()#設置事件,一旦set,那么讀者wait就有返回了,讀者可以繼續運行了
    print("write:寫好了")
    time.sleep(2)#等人讀
    event.clear()#清除事件


event=threading.Event() #創建事件對象

t1=threading.Thread(target=write)
t2=threading.Thread(target=read)

t1.start()
t2.start()
t1.join()
t2.join()

"""結果顯示:讀者確實一直在等待寫者寫好"""

Python多線程操作之互斥鎖、遞歸鎖、信號量、事件實例詳解

更多關于Python相關內容感興趣的讀者可查看本站專題:《Python進程與線程操作技巧總結》、《Python數據結構與算法教程》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》、《Python入門與進階經典教程》、《Python+MySQL數據庫程序設計入門教程》及《Python常見數據庫操作技巧匯總》

希望本文所述對大家Python程序設計有所幫助。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

河间市| 锡林浩特市| 贵南县| 平湖市| 东方市| 建阳市| 密山市| 斗六市| 唐河县| 穆棱市| 澄迈县| 南安市| 大姚县| 正定县| 沛县| 遂川县| 阳春市| 温泉县| 娱乐| 阜城县| 改则县| 淳化县| 新源县| 巴彦淖尔市| 蓝山县| 桂阳县| 乐陵市| 桦南县| 永平县| 莱阳市| 阿勒泰市| 揭东县| 大石桥市| 景谷| 尉氏县| 石景山区| 六盘水市| 郑州市| 类乌齐县| 黑河市| 上犹县|