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

舉例講解Python中的死鎖、可重入鎖和互斥鎖

 更新時(shí)間:2015年11月05日 15:40:59   投稿:goldensun  
這篇文章主要介紹了舉例講解Python中的死鎖、可重入鎖和互斥鎖,盡管線程編程方面Python的GIL問(wèn)題老生常談...需要的朋友可以參考下

一、死鎖

簡(jiǎn)單來(lái)說(shuō),死鎖是一個(gè)資源被多次調(diào)用,而多次調(diào)用方都未能釋放該資源就會(huì)造成死鎖,這里結(jié)合例子說(shuō)明下兩種常見(jiàn)的死鎖情況。

1、迭代死鎖

該情況是一個(gè)線程“迭代”請(qǐng)求同一個(gè)資源,直接就會(huì)造成死鎖:

import threading
import time
class MyThread(threading.Thread):
  def run(self):
    global num
    time.sleep(1)
    if mutex.acquire(1):
      num = num+1
      msg = self.name+' set num to '+str(num)
      print msg
      mutex.acquire()
      mutex.release()
      mutex.release()
num = 0
mutex = threading.Lock()
def test():
  for i in range(5):
    t = MyThread()
    t.start()
if __name__ == '__main__':
  test()

上例中,在run函數(shù)的if判斷中第一次請(qǐng)求資源,請(qǐng)求后還未 release ,再次acquire,最終無(wú)法釋放,造成死鎖。這里例子中通過(guò)將print下面的兩行注釋掉就可以正常執(zhí)行了 ,除此之外也可以通過(guò)可重入鎖解決,后面會(huì)提到。

2、互相調(diào)用死鎖

上例中的死鎖是在同一個(gè)def函數(shù)內(nèi)多次調(diào)用造成的,另一種情況是兩個(gè)函數(shù)中都會(huì)調(diào)用相同的資源,互相等待對(duì)方結(jié)束的情況。如果兩個(gè)線程分別占有一部分資源并且同時(shí)等待對(duì)方的資源,就會(huì)造成死鎖。

import threading
import time
class MyThread(threading.Thread):
  def do1(self):
    global resA, resB
    if mutexA.acquire():
       msg = self.name+' got resA'
       print msg
       if mutexB.acquire(1):
         msg = self.name+' got resB'
         print msg
         mutexB.release()
       mutexA.release()
  def do2(self):
    global resA, resB
    if mutexB.acquire():
       msg = self.name+' got resB'
       print msg
       if mutexA.acquire(1):
         msg = self.name+' got resA'
         print msg
         mutexA.release()
       mutexB.release()
  def run(self):
    self.do1()
    self.do2()
resA = 0
resB = 0
mutexA = threading.Lock()
mutexB = threading.Lock()
def test():
  for i in range(5):
    t = MyThread()
    t.start()
if __name__ == '__main__':
  test()

這個(gè)死鎖的示例稍微有點(diǎn)復(fù)雜。具體可以理下。

二、可重入鎖

為了支持在同一線程中多次請(qǐng)求同一資源,python提供了“可重入鎖”:threading.RLock。RLock內(nèi)部維護(hù)著一個(gè)Lock和一個(gè)counter變量,counter記錄了acquire的次數(shù),從而使得資源可以被多次require。直到一個(gè)線程所有的acquire都被release,其他的線程才能獲得資源。這里以例1為例,如果使用RLock代替Lock,則不會(huì)發(fā)生死鎖:

import threading
import time
class MyThread(threading.Thread):
  def run(self):
    global num
    time.sleep(1)
    if mutex.acquire(1):
      num = num+1
      msg = self.name+' set num to '+str(num)
      print msg
      mutex.acquire()
      mutex.release()
      mutex.release()
num = 0
mutex = threading.RLock()
def test():
  for i in range(5):
    t = MyThread()
    t.start()
if __name__ == '__main__':
  test()

和上面那個(gè)例子的不同之處在于threading.Lock()換成了threading.RLock() 。

三、互斥鎖
python threading模塊有兩類鎖:互斥鎖(threading.Lock )和可重用鎖(threading.RLock)。兩者的用法基本相同,具體如下:

lock = threading.Lock()
lock.acquire()
dosomething……
lock.release()

RLock的用法是將threading.Lock()修改為threading.RLock()。便于理解,先來(lái)段代碼:

[root@361way lock]# cat lock1.py
#!/usr/bin/env python
# coding=utf-8
import threading              # 導(dǎo)入threading模塊
import time               # 導(dǎo)入time模塊
class mythread(threading.Thread):    # 通過(guò)繼承創(chuàng)建類
  def __init__(self,threadname):   # 初始化方法
    # 調(diào)用父類的初始化方法
    threading.Thread.__init__(self,name = threadname)
  def run(self):             # 重載run方法
    global x         # 使用global表明x為全局變量
    for i in range(3):
      x = x + 1
    time.sleep(5)     # 調(diào)用sleep函數(shù),讓線程休眠5秒
    print x
tl = []               # 定義列表
for i in range(10):
  t = mythread(str(i))        # 類實(shí)例化
  tl.append(t)           # 將類對(duì)象添加到列表中
x=0                 # 將x賦值為0
for i in tl:
  i.start() 

這里執(zhí)行的結(jié)果和想想的不同,結(jié)果如下:

[root@361way lock]# python lock1.py
30
30
30
30
30
30
30
30
30
30

為什么結(jié)果都是30呢?關(guān)鍵在于global 行和 time.sleep行。

1、由于x是一個(gè)全局變量,所以每次循環(huán)后 x 的值都是執(zhí)行后的結(jié)果值;

2、由于該代碼是多線程的操作,所以在sleep 等待的時(shí)候,之前已經(jīng)執(zhí)行完成的線程會(huì)在這等待,而后續(xù)的進(jìn)程在等待的5秒這段時(shí)間也執(zhí)行完成 ,等待print。同樣由于global 的原理,x被重新斌值。所以打印出的結(jié)果全是30 ;

3、便于理解,可以嘗試將sleep等注釋,你再看下結(jié)果,就會(huì)發(fā)現(xiàn)有不同。

在實(shí)際應(yīng)用中,如抓取程序等,也會(huì)出現(xiàn)類似于sleep等待的情況。在前后調(diào)用有順序或打印有輸出的時(shí)候,就會(huì)現(xiàn)并發(fā)競(jìng)爭(zhēng),造成結(jié)果或輸出紊亂。這里就引入了鎖的概念,上面的代碼修改下,如下:

[root@361way lock]# cat lock2.py
#!/usr/bin/env python
# coding=utf-8
import threading              # 導(dǎo)入threading模塊
import time               # 導(dǎo)入time模塊
class mythread(threading.Thread):          # 通過(guò)繼承創(chuàng)建類
  def __init__(self,threadname):         # 初始化方法
    threading.Thread.__init__(self,name = threadname)
  def run(self):             # 重載run方法
    global x            # 使用global表明x為全局變量
    lock.acquire()           # 調(diào)用lock的acquire方法
    for i in range(3):
      x = x + 1
    time.sleep(5)      # 調(diào)用sleep函數(shù),讓線程休眠5秒
    print x
    lock.release()        # 調(diào)用lock的release方法
lock = threading.Lock()        # 類實(shí)例化
tl = []             # 定義列表
for i in range(10):
  t = mythread(str(i))      # 類實(shí)例化
  tl.append(t)       # 將類對(duì)象添加到列表中
x=0            # 將x賦值為0
for i in tl:
  i.start()           # 依次運(yùn)行線程

執(zhí)行的結(jié)果如下:

[root@361way lock]# python lock2.py
3
6
9
12
15
18
21
24
27
30

加鎖的結(jié)果會(huì)造成阻塞,而且會(huì)造成開(kāi)鎖大。會(huì)根據(jù)順序由并發(fā)的多線程按順序輸出,如果后面的線程執(zhí)行過(guò)快,需要等待前面的進(jìn)程結(jié)束后其才能結(jié)束 --- 寫的貌似有點(diǎn)像隊(duì)列的概念了 ,不過(guò)在加鎖的很多場(chǎng)景下確實(shí)可以通過(guò)隊(duì)列去解決。

相關(guān)文章

  • python聊天室(雖然很簡(jiǎn)潔,但是可以用)

    python聊天室(雖然很簡(jiǎn)潔,但是可以用)

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • python3 下載網(wǎng)絡(luò)圖片代碼實(shí)例

    python3 下載網(wǎng)絡(luò)圖片代碼實(shí)例

    這篇文章主要介紹了python3 下載網(wǎng)絡(luò)圖片代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Python 實(shí)現(xiàn)子類獲取父類的類成員方法

    Python 實(shí)現(xiàn)子類獲取父類的類成員方法

    今天小編就為大家分享一篇Python 實(shí)現(xiàn)子類獲取父類的類成員方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • 基于Python中求和函數(shù)sum的用法詳解

    基于Python中求和函數(shù)sum的用法詳解

    今天小編就為大家分享一篇基于Python中求和函數(shù)sum的用法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • pandas計(jì)算最大連續(xù)間隔的方法

    pandas計(jì)算最大連續(xù)間隔的方法

    今天小編就為大家分享一篇pandas計(jì)算最大連續(xù)間隔的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • python學(xué)生管理系統(tǒng)代碼實(shí)現(xiàn)

    python學(xué)生管理系統(tǒng)代碼實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了python學(xué)生管理系統(tǒng)代碼實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 一文教你掌握Python中Lambda表達(dá)式的5種實(shí)用技巧

    一文教你掌握Python中Lambda表達(dá)式的5種實(shí)用技巧

    在Python編程的宇宙里,有一個(gè)強(qiáng)大而靈活的工具經(jīng)常被高效的程序員所利用——那就是Lambda表達(dá)式,下面就讓我們深入了解Lambda表達(dá)式的妙用吧
    2024-01-01
  • python的Crypto模塊實(shí)現(xiàn)AES加密實(shí)例代碼

    python的Crypto模塊實(shí)現(xiàn)AES加密實(shí)例代碼

    這篇文章主要介紹了python的Crypto模塊實(shí)現(xiàn)AES加密實(shí)例代碼,簡(jiǎn)單介紹了實(shí)現(xiàn)步驟,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • 利用Python實(shí)現(xiàn)模擬登錄知乎

    利用Python實(shí)現(xiàn)模擬登錄知乎

    這篇文章主要為大家介紹了如何利用Python實(shí)現(xiàn)模擬登陸知乎功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定幫助,需要的可以參考一下
    2022-05-05
  • PyQt5 PySide2 觸摸測(cè)試功能的實(shí)現(xiàn)代碼

    PyQt5 PySide2 觸摸測(cè)試功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了PyQt5 PySide2 觸摸測(cè)試功能的實(shí)現(xiàn),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04

最新評(píng)論

萍乡市| 和龙市| 桐乡市| 高密市| 莱西市| 麟游县| 奉新县| 雷波县| 应用必备| 金川县| 漾濞| 苍山县| 巴里| 富宁县| 临城县| 佳木斯市| 上饶县| 大余县| 兴山县| 陈巴尔虎旗| 尼勒克县| 贵港市| 沿河| 台湾省| 营山县| 永顺县| 九龙坡区| 富民县| 武定县| 宜城市| 蕲春县| 萝北县| 湘潭县| 布拖县| 云浮市| 泰宁县| 徐州市| 会宁县| 永顺县| 穆棱市| 嵩明县|