最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python多線程操作之互斥鎖、遞歸鎖、信號(hào)量、事件實(shí)例詳解

 更新時(shí)間:2020年03月24日 10:08:34   作者:隨風(fēng)行云  
這篇文章主要介紹了Python多線程操作之互斥鎖、遞歸鎖、信號(hào)量、事件,結(jié)合實(shí)例形式詳細(xì)分析了Python多線程操作互斥鎖、遞歸鎖、信號(hào)量、事件相關(guān)概念、原理、用法與操作注意事項(xiàng),需要的朋友可以參考下

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

互斥鎖:

  • 為什么要有互斥鎖:由于多線程是并行的,如果某一線程取出了某一個(gè)數(shù)據(jù)將要進(jìn)行操作,但它還沒(méi)有那么快執(zhí)行完操作,這時(shí)候如果另外一個(gè)線程也要操作這個(gè)數(shù)據(jù),那么這個(gè)數(shù)據(jù)可能會(huì)因?yàn)閮纱尾僮鞫l(fā)生錯(cuò)誤
import time,threading

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

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

  x=5
  print(x)

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

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

image

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

使用互斥鎖來(lái)更改上段代碼

import time,threading

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

lock=threading.Lock()#生成一個(gè)鎖對(duì)象
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多說(shuō)明,由于受到鎖的影響,run2要等待run1釋放lock,所以變成了串行

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

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

image


遞歸鎖:

  • 為什么要有遞歸鎖:互斥鎖本質(zhì)上是阻止其他線程進(jìn)入,如果有兩個(gè)需要阻止其他線程進(jìn)入的操作【像兩個(gè)人過(guò)獨(dú)木橋】,那么需要兩個(gè)鎖,而想要鎖上第二個(gè)如果直接用第一個(gè)鎖的acquire會(huì)失敗,因?yàn)榈谝粋€(gè)鎖還沒(méi)release,我們可以選擇再定義一個(gè)互斥鎖對(duì)象來(lái)acquire,但這僅僅是兩層的情況下,如果多層的吧,那么就需要定義好幾個(gè)互斥鎖對(duì)象了【而且由于對(duì)象變多,有時(shí)候會(huì)因?yàn)榛ハ嗾{(diào)用鎖而發(fā)生死鎖】。遞歸鎖就是為了處理這種情況,遞歸鎖對(duì)象允許多次acquire和多次release
    • 發(fā)生死鎖的情況[A拿到A鎖,想要拿B鎖,B拿著B鎖,想要A鎖]

【以過(guò)獨(dú)木橋?yàn)槔浚簶蛑荒苋菀粋€(gè)人通過(guò),A只能看得到北邊橋上有沒(méi)有人,看不到南邊橋有沒(méi)有人,當(dāng)他看到北邊橋沒(méi)人就會(huì)過(guò)橋,等到他到橋中間才能看到南邊橋有沒(méi)有人,B情況相反:【于是當(dāng)兩個(gè)人一起過(guò)橋的時(shí)候就會(huì)發(fā)生死鎖】

import threading,time

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

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


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

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

tA.join()
tB.join()

image

  • 遞歸鎖的本質(zhì)是:本質(zhì)上還是一個(gè)鎖,但如果在一個(gè)線程里面可以多次acquire。【因?yàn)橹挥幸粋€(gè)鎖,所以不會(huì)發(fā)生互相調(diào)用的死鎖,而因?yàn)榭梢远啻握{(diào)用,所以可以鎖多次】
  • 如何使用遞歸鎖:
    1. 定義一個(gè)鎖對(duì)象:遞歸鎖對(duì)象=threading.RLock()
    2. 請(qǐng)求鎖:鎖對(duì)象.acquire()
    3. 釋放鎖:鎖對(duì)象.release()

使用遞歸鎖來(lái)解決上面的死鎖問(wèn)題:

import threading,time

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

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


lock=threading.RLock()

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

tA.join()
tB.join()

image

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


信號(hào)量:

  • 什么是信號(hào)量:

image

信號(hào)量可以限制進(jìn)入的線程的數(shù)量。

  • 如何使用信號(hào)量:
    1. 創(chuàng)建信號(hào)量對(duì)象:信號(hào)量對(duì)象=threading.BoundedSemaphore(x),x是限制進(jìn)程的數(shù)量
    2. 當(dāng)有進(jìn)程需要進(jìn)入的時(shí)候,調(diào)用acquire()來(lái)減少信號(hào)量:信號(hào)量對(duì)象.acquire()
    3. 當(dāng)有進(jìn)程離開(kāi)的時(shí)候,調(diào)用release()來(lái)增加信號(hào)量:信號(hào)量對(duì)象.release()
import threading,time


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

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

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

for i in range(4):
  print("")#為了把結(jié)果分割,可以清楚看出分為了三組
  time.sleep(1.5)
#結(jié)果分為三組是因?yàn)檫\(yùn)行的太快了,三個(gè)線程裝入的時(shí)間差太小

image


事件:

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


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

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


event=threading.Event() #創(chuàng)建事件對(duì)象

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

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

"""結(jié)果顯示:讀者確實(shí)一直在等待寫者寫好"""

image

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫(kù)程序設(shè)計(jì)入門教程》及《Python常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • NumPy 數(shù)組屬性的具體使用

    NumPy 數(shù)組屬性的具體使用

    本文主要介紹了NumPy 數(shù)組屬性的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • python安裝包site-packages的方法步驟

    python安裝包site-packages的方法步驟

    本文主要介紹了python安裝包site-packages的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-01-01
  • 在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式

    在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式

    這篇文章主要介紹了在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • PyQt4實(shí)現(xiàn)下拉菜單可供選擇并打印出來(lái)

    PyQt4實(shí)現(xiàn)下拉菜單可供選擇并打印出來(lái)

    這篇文章主要為大家詳細(xì)介紹了PyQt4實(shí)現(xiàn)下拉菜單可供選擇并打印出來(lái),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Python使用zip合并相鄰列表項(xiàng)的方法示例

    Python使用zip合并相鄰列表項(xiàng)的方法示例

    這篇文章主要介紹了Python使用zip合并相鄰列表項(xiàng)的方法,涉及zip、iter函數(shù)合并相鄰列表項(xiàng)、切片等相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03
  • Python pickle模塊用法實(shí)例

    Python pickle模塊用法實(shí)例

    這篇文章主要介紹了Python pickle模塊用法實(shí)例,python的pickle模塊實(shí)現(xiàn)了基本的數(shù)據(jù)序列和反序列化,需要的朋友可以參考下
    2015-04-04
  • python計(jì)算一個(gè)序列的平均值的方法

    python計(jì)算一個(gè)序列的平均值的方法

    這篇文章主要介紹了python計(jì)算一個(gè)序列的平均值的方法,涉及Python遞歸遍歷與數(shù)學(xué)計(jì)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • Python爬蟲中的并發(fā)編程詳解

    Python爬蟲中的并發(fā)編程詳解

    Python爬蟲中的并發(fā)編程是一種優(yōu)化爬取速度、解決阻塞問(wèn)題、優(yōu)化資源利用的方式。常用的并發(fā)編程模塊包括多線程、多進(jìn)程、協(xié)程等,通過(guò)并發(fā)處理多個(gè)任務(wù),可以提高爬取效率,節(jié)省爬蟲資源利用成本。同時(shí),還需注意線程安全、共享資源問(wèn)題等并發(fā)編程中的常見(jiàn)陷阱
    2023-05-05
  • python 實(shí)現(xiàn)保存最新的三份文件,其余的都刪掉

    python 實(shí)現(xiàn)保存最新的三份文件,其余的都刪掉

    今天小編就為大家分享一篇python 實(shí)現(xiàn)保存最新的三份文件,其余的都刪掉,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法詳解

    VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法詳解

    這篇文章主要介紹了VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法,較為詳細(xì)的分析了VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的具體步驟、相關(guān)命令與操作注意事項(xiàng),需要的朋友可以參考下
    2019-07-07

最新評(píng)論

兴宁市| 响水县| 阿合奇县| 峨山| 林周县| 阿拉善右旗| 利川市| 大同市| 岑溪市| 英吉沙县| 吴桥县| 内丘县| 承德市| 如东县| 黄梅县| 咸丰县| 社旗县| 临沭县| 九台市| 神池县| 阳原县| 墨玉县| 甘孜县| 通化县| 大港区| 会同县| 黑山县| 津南区| 龙海市| 射阳县| 文山县| 周宁县| 雅江县| 新河县| 济南市| 哈巴河县| 平江县| 赤峰市| 宁强县| 克什克腾旗| 河津市|