亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原(yuan)創

Python并發編程(二)

2023-09-08 09:30:33
4
0

上(shang)一篇博客介(jie)(jie)紹(shao)了Python并發編(bian)程的(de)(de)基本知(zhi)識,感興(xing)趣的(de)(de)可以(yi)(yi)到專利找(zhao)到上(shang)一篇文章,本文主(zhu)要介(jie)(jie)紹(shao)如何(he)開啟多線(xian)程,以(yi)(yi)及多線(xian)程在(zai)提升效率的(de)(de)同時會存在(zai)哪些問題

Python通過標準庫的 threading 模(mo)塊來管理線程。這個模(mo)塊提供(gong)了很多不(bu)錯的特(te)性,讓(rang)線程變得無比簡(jian)單,打開(kai)threading.py文件,可(ke)以(yi)到(dao)如下(xia)類或者方(fang)法

線(xian)程(cheng)(cheng)模塊常用(yong)的(de)主要組件有,Thread、Event、Lock、RLock、Semaphore、Timer等等,他們可以用(yong)來(lai)開啟線(xian)程(cheng)(cheng)、保證線(xian)程(cheng)(cheng)間的(de)安全、線(xian)程(cheng)(cheng)間的(de)通信等等

使用線(xian)程最簡單的一個(ge)(ge)方法是,用一個(ge)(ge)目標函數實例化(hua)一個(ge)(ge)Thread然后調用 start() 方法啟動它。示例如下(xia)

import threading

def function(i):
    print ("function called by thread %i\n" % i)
    return

threads = []

for i in range(5):
    t = threading.Thread(target=function , args=(i, ))
    threads.append(t)
    t.start()
    t.join()

上述代碼就可以開啟(qi)5個(ge)線程執行(xing)function函數

Thread()參數解釋如(ru)下

  • group: 一般(ban)設置為 None ,這(zhe)是(shi)為以(yi)后的一(yi)些特性預留的

  • target: 當線程啟動的(de)(de)時候要執行的(de)(de)函數(shu)

  • name: 線程(cheng)的名字,默認(ren)會分配(pei)一個唯一名字 Thread-N

  • args: 傳遞給 target 的參數,要使用tuple類型

  • kwargs: 同上,使用字(zi)典類(lei)型(xing)dict

Thread類(lei)定義(yi)的常(chang)用方法(fa)如下(xia)

  1. start(): 啟動線(xian)程,并(bing)執行 run() 方法。

  2. run(): 線程啟動后執行的方法,可以在(zai)子類中(zhong)重寫(xie)。

  3. join([timeout]): 等待線程結束,可選參數 timeout 指定最長等待時間(jian)。

  4. is_alive(): 判斷線程(cheng)是(shi)否仍然存(cun)活。

  5. name: 線(xian)程名(ming)稱的(de)屬性,可以在實例化時指定或修改。

  6. setDaemon(daemonic): 設置線程是否為守(shou)護線程,默認為 False。守(shou)護線程會在(zai)主線程結束(shu)時自動退出。

  7. getName(): 獲(huo)取線程(cheng)名稱。

  8. setName(name): 設置線程名稱(cheng)。

多個(ge)(ge)線程操作同一個(ge)(ge)資源,并且至少有(you)一個(ge)(ge)可(ke)以改變數據,又沒有(you)同步機(ji)制的條件(jian)下,就會產生競(jing)爭(zheng)條件(jian),可(ke)能(neng)會導致執(zhi)行(xing)無效代碼、bug、或異常行(xing)為。

這時候可(ke)以用Lock來(lai)保(bao)持線程(cheng)同步,例(li)如下(xia)列(lie)代碼,在下(xia)面(mian)的代碼中,我們(men)有(you)兩(liang)個(ge)函數(shu): increment()decrement() 。第一(yi)個(ge)(ge)(ge)函(han)數對共(gong)享資(zi)源執行加(jia)1的操作,另一(yi)個(ge)(ge)(ge)函(han)數執行減1.兩(liang)個(ge)(ge)(ge)函(han)數分別使用線程(cheng)封裝。除此之外,每一(yi)個(ge)(ge)(ge)函(han)數都有一(yi)個(ge)(ge)(ge)循環重復執行操作。我們想要保證,通過對共(gong)享資(zi)源的管理,執行結(jie)果是共(gong)享資(zi)源最后等(deng)于初始值0.

# -*- coding: utf-8 -*-

import threading

shared_resource_with_lock = 0
shared_resource_with_no_lock = 0
COUNT = 10000000
shared_resource_lock = threading.Lock()

# 有鎖的情況
def increment_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock += 1
        shared_resource_lock.release()

def decrement_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock -= 1
        shared_resource_lock.release()

# 沒有鎖的情況
def increment_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock += 1

def decrement_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock -= 1

if __name__ == "__main__":
    t1 = threading.Thread(target=increment_with_lock)
    t2 = threading.Thread(target=decrement_with_lock)
    t3 = threading.Thread(target=increment_without_lock)
    t4 = threading.Thread(target=decrement_without_lock)
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()
    print ("the value of shared variable with lock management is %s" % shared_resource_with_lock)
    print ("the value of shared variable with race condition is %s" % shared_resource_with_no_lock)

輸出

the value of shared variable with lock management is 0
the value of shared variable with race condition is -242686

可(ke)以看到(dao)未加鎖的程序(xu)出(chu)(chu)現了錯誤(wu),如(ru)果你運行了示例代碼沒有出(chu)(chu)錯,可(ke)以把COUNT值調(diao)大試試

但加鎖有什么缺點(dian)呢,第(di)一會(hui)消耗資(zi)源,第(di)二如(ru)果程序中(zhong)有多(duo)個(ge)鎖存在,可能會(hui)造成死鎖,導致程序一直卡住,我們設有兩個(ge)并發的線程( 線程A線程B ),需要 資源1資(zi)源2 .假(jia)設 線(xian)程A 需要 資源1線程B 需要 資源2 .在(zai)這種(zhong)情況下,兩(liang)個線程都使用各(ge)自的(de)鎖,目前(qian)為止沒有沖突。現(xian)在(zai)假(jia)設,在(zai)雙方釋放鎖之前(qian), 線程A 需(xu)要 資源2 的(de)鎖, 線程B 需(xu)要 資源1 的鎖,沒有資源線程不會繼續執行(xing)。這就出現了死鎖問題。

下篇文章介紹如何解決(jue)多線程的死鎖問題(ti)

0條評論
0 / 1000
張****宇
5文(wen)章數
0粉絲數
張****宇
5 文章 | 0 粉絲
張****宇
5文(wen)章數
0粉絲(si)數(shu)
張****宇
5 文章(zhang) | 0 粉絲
原創(chuang)

Python并發編程(二)

2023-09-08 09:30:33
4
0

上(shang)一篇博(bo)客介紹了Python并發(fa)編程(cheng)的基(ji)本(ben)知識,感興趣的可以到專利找到上(shang)一篇文章(zhang),本(ben)文主要介紹如何開啟多線程(cheng),以及多線程(cheng)在提升效率的同時會存在哪些問題

Python通過(guo)標準庫的 threading 模塊(kuai)來管理線程。這個模塊(kuai)提供了很多(duo)不錯的(de)特(te)性,讓線程變(bian)得無比簡單,打(da)開(kai)threading.py文(wen)件,可以到如下類或者方(fang)法(fa)

線(xian)(xian)(xian)程(cheng)(cheng)模塊常用(yong)的主要組件有,Thread、Event、Lock、RLock、Semaphore、Timer等等,他(ta)們可以(yi)用(yong)來開啟線(xian)(xian)(xian)程(cheng)(cheng)、保證線(xian)(xian)(xian)程(cheng)(cheng)間的安全、線(xian)(xian)(xian)程(cheng)(cheng)間的通信等等

使用線程最簡單的(de)一(yi)個(ge)方法是,用一(yi)個(ge)目標函數實例化一(yi)個(ge)Thread然后(hou)調用 start() 方法啟(qi)動它。示例如下

import threading

def function(i):
    print ("function called by thread %i\n" % i)
    return

threads = []

for i in range(5):
    t = threading.Thread(target=function , args=(i, ))
    threads.append(t)
    t.start()
    t.join()

上述(shu)代(dai)碼就(jiu)可以開(kai)啟5個(ge)線(xian)程執行function函數

Thread()參數解釋如(ru)下

  • group: 一般設置為 None ,這是為以后的(de)一(yi)些特性預留的(de)

  • target: 當線程啟(qi)動的時候要執(zhi)行的函數(shu)

  • name: 線(xian)程的名字(zi),默認會分(fen)配一個唯一名字(zi) Thread-N

  • args: 傳(chuan)遞(di)給(gei) target 的參數,要使用tuple類(lei)型

  • kwargs: 同上,使用字典類型dict

Thread類定義的常用(yong)方法如(ru)下(xia)

  1. start(): 啟(qi)動線程,并執行(xing) run() 方法。

  2. run(): 線程啟(qi)動后執(zhi)行(xing)的(de)方(fang)法,可(ke)以在(zai)子類中重寫。

  3. join([timeout]): 等(deng)待線程結(jie)束,可選參數 timeout 指定最長等(deng)待時間。

  4. is_alive(): 判斷(duan)線程是否仍然存活(huo)。

  5. name: 線(xian)程名稱的屬性,可以在實例化時指(zhi)定或修改。

  6. setDaemon(daemonic): 設(she)置線(xian)程(cheng)(cheng)是否為守護(hu)線(xian)程(cheng)(cheng),默(mo)認為 False。守護(hu)線(xian)程(cheng)(cheng)會在主(zhu)線(xian)程(cheng)(cheng)結束時自動退(tui)出。

  7. getName(): 獲取線程名(ming)稱。

  8. setName(name): 設(she)置線程名稱。

多個線(xian)程操作同一個資源,并且至少(shao)有一個可(ke)以改變數據,又沒有同步(bu)機制的條件下,就會產生(sheng)競(jing)爭條件,可(ke)能會導致執(zhi)行無(wu)效代碼、bug、或異(yi)常行為。

這(zhe)時候(hou)可以用Lock來保(bao)持線(xian)程同步,例如下(xia)列代碼(ma),在下(xia)面的(de)代碼(ma)中,我們有兩個(ge)函數(shu): increment() 和(he) decrement() 。第一個(ge)函數對(dui)共(gong)享(xiang)資(zi)源執行(xing)加(jia)1的操作,另一個(ge)函數執行(xing)減1.兩個(ge)函數分別使用線(xian)程封裝。除此(ci)之外,每一個(ge)函數都有一個(ge)循環重復執行(xing)操作。我們(men)想要(yao)保證,通過對(dui)共(gong)享(xiang)資(zi)源的管理(li),執行(xing)結(jie)果是共(gong)享(xiang)資(zi)源最(zui)后(hou)等于初(chu)始值(zhi)0.

# -*- coding: utf-8 -*-

import threading

shared_resource_with_lock = 0
shared_resource_with_no_lock = 0
COUNT = 10000000
shared_resource_lock = threading.Lock()

# 有鎖的情況
def increment_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock += 1
        shared_resource_lock.release()

def decrement_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock -= 1
        shared_resource_lock.release()

# 沒有鎖的情況
def increment_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock += 1

def decrement_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock -= 1

if __name__ == "__main__":
    t1 = threading.Thread(target=increment_with_lock)
    t2 = threading.Thread(target=decrement_with_lock)
    t3 = threading.Thread(target=increment_without_lock)
    t4 = threading.Thread(target=decrement_without_lock)
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()
    print ("the value of shared variable with lock management is %s" % shared_resource_with_lock)
    print ("the value of shared variable with race condition is %s" % shared_resource_with_no_lock)

輸出

the value of shared variable with lock management is 0
the value of shared variable with race condition is -242686

可(ke)以看到未加(jia)鎖(suo)的程序出現了(le)錯誤(wu),如(ru)果你運行了(le)示例代碼沒有出錯,可(ke)以把COUNT值調大試試

但加鎖(suo)有什么缺點呢,第(di)一會消耗資源,第(di)二如(ru)果程序中有多個(ge)鎖(suo)存在,可能會造成死鎖(suo),導致程序一直卡住(zhu),我們設有兩(liang)個(ge)并發(fa)的線程( 線程(cheng)A線程B ),需要(yao) 資源1資源2 .假(jia)設 線程A 需要 資源1線程B 需(xu)要(yao) 資源(yuan)2 .在(zai)這種(zhong)情況下,兩個(ge)線程都使用各自的(de)鎖,目前為止沒(mei)有(you)沖突(tu)。現在(zai)假設(she),在(zai)雙(shuang)方釋(shi)放鎖之前, 線程A 需要 資(zi)源2 的鎖, 線(xian)程B 需要(yao) 資源1 的鎖(suo)(suo),沒有資(zi)源線(xian)程不會繼(ji)續執行。這就(jiu)出現了死鎖(suo)(suo)問題。

下篇文(wen)章介紹如何解決多線程的死鎖問題(ti)

文章來自個人專欄
文章(zhang) | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0