亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Python系統(tǒng)編程之線程

XboxYan / 2097人閱讀

摘要:可以將它們認(rèn)為是在一個(gè)主進(jìn)程或主線程中并行運(yùn)行的一些迷你進(jìn)程。因此與進(jìn)程相比,線程之間的信息共享和通信更加容易。當(dāng)上鎖的線程執(zhí)行完畢進(jìn)行解鎖,堵塞的線程就爭(zhēng)奪到上鎖權(quán)而進(jìn)行代碼塊的運(yùn)行。

threading模塊 線程簡(jiǎn)述

線程(輕量級(jí)進(jìn)程)與進(jìn)程類似,不過它們是在同一個(gè)進(jìn)程下執(zhí)行的,并共享相同的上下文。可以將它們認(rèn)為是在一個(gè)主進(jìn)程或"主線程"中并行運(yùn)行的一些"迷你進(jìn)程"。

線程包括開始、執(zhí)行順序和結(jié)束三部分。它有一個(gè)指令指針,用于記錄運(yùn)行的上下文。它其他線程運(yùn)行時(shí),它可以被搶占(中斷)和臨時(shí)掛起(睡眠/加鎖)---這種做法叫做讓步(yielding)。

多線程的創(chuàng)建

使用Thread類,可以有很多方法來創(chuàng)建線程,其中常用的有:

創(chuàng)建Thread的示例,傳給它一個(gè)函數(shù);

派生Thread的子類,重新run方法,并創(chuàng)建子類的實(shí)例。

示例1:創(chuàng)建Thread的實(shí)例,傳給它一個(gè)函數(shù)

from threading import Thread
import time

def test():
    print("---hello-world---")
    time.sleep(1)


for i in range(5):
    #創(chuàng)建線程,線程執(zhí)行的任務(wù)是target指定的函數(shù),如果函數(shù)需要傳入?yún)?shù),則可以指定args=(),或者kwargs={}
    t = Thread(target=test)
    t.start()

運(yùn)行結(jié)果:

---hello-world---
---hello-world---
---hello-world---
---hello-world---
---hello-world---

示例2:使用Thread子類創(chuàng)建線程

import threading
import time

# 自定義類繼承threading類
class myThread(threading.Thread):
    # 重新run方法
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I"m " + self.name+" @ "+str(i)
            print(msg)

if __name__ == "__main__":
    # 創(chuàng)建線程
    t = myThread()
    t.start()

運(yùn)行結(jié)果:

I"m Thread-1 @ 0
I"m Thread-1 @ 1
I"m Thread-1 @ 2

python的threading.Thread類有一個(gè)run方法,用于定義線程的功能函數(shù),可以在自己的線程類中覆蓋該方法。而創(chuàng)建自己的線程實(shí)例后,通過Thread類的start方法,可以啟動(dòng)該線程,交給python虛擬機(jī)進(jìn)行調(diào)度,當(dāng)該線程獲得執(zhí)行的機(jī)會(huì)時(shí),就會(huì)調(diào)用run方法執(zhí)行線程。

多線程共享全局變量

在一個(gè)進(jìn)程中,多個(gè)線程之間是共享全局變量的,即一個(gè)線程修改了全局變量,另外一個(gè)線程在此之后獲取的這個(gè)全局變量是被修改后的。比如下面例子:

from threading import Thread
import time

num = 100

def thread1():
    global num
    for i in range(3):
        num += 1
    print("I"am Thread1 ."  +  " my num is "+str(num))

def thread2():
    print("I"am Thread2. " +" my num is "+ str(num))

t1 = Thread(target=thread1)
t1.start()

# 讓程序睡眠1秒鐘,確保線程1執(zhí)行完畢。
time.sleep(1)
t2 = Thread(target=thread2)
t2.start()

運(yùn)行結(jié)果:

I"am Thread1. my num is 103
I"am Thread2.  my num is 103

線程關(guān)于全局變量注意點(diǎn)
在一個(gè)進(jìn)程內(nèi)的所有線程共享全局變量,能夠在不適用其他方式的前提下完成多線程之間的數(shù)據(jù)共享(這點(diǎn)要比多進(jìn)程要好)

一個(gè)進(jìn)程中的各個(gè)線程與主線程共享同一片數(shù)據(jù)空間。因此與進(jìn)程相比,線程之間的信息共享和通信更加容易。在一個(gè)程序中,線程的執(zhí)行是:每個(gè)線程運(yùn)行一小會(huì),然后讓步給其他線程(再次排隊(duì)等待更多的CPU時(shí)間)。在整個(gè)進(jìn)程的執(zhí)行過程中,每個(gè)線程執(zhí)行它自己特定的任務(wù),在必要時(shí)和其他線程進(jìn)行通信。

當(dāng)然,這種共享是有風(fēng)險(xiǎn)的。如果兩個(gè)或多個(gè)線程訪問同一片數(shù)據(jù),由于數(shù)據(jù)的訪問順序不同可能導(dǎo)致結(jié)果不一致。這種情況叫競(jìng)態(tài)條件。辛運(yùn)的是,大多數(shù)線程庫都有一些同步源語,以允許線程管理器控制執(zhí)行和訪問。

同步和互斥鎖 同步

一般在多線程代碼中,總有一些函數(shù)或者代碼塊不希望被多個(gè)線程同時(shí)執(zhí)行,如果有兩個(gè)線程運(yùn)行的順序發(fā)生變化,就有可能造成代碼的執(zhí)行軌跡或行為不同,產(chǎn)生不一樣的數(shù)據(jù)。這時(shí)候就需要使用同步了。

同步可以理解為協(xié)同步調(diào),按預(yù)定的先后次序進(jìn)行運(yùn)行,比如你先說,我再講。

示例1:多個(gè)線程對(duì)全局變量修改的bug

from threading import Thread
import time

num = 0    
def work1():
    global num
    for i in range(1000000):
        num += 1
    print("-work1-num:%d"%num)    
def work2():
    global num
    for i in range(1000000):
        num += 1
    print("-work2-num:%d"%num)

t1 = Thread(target=work1)
t1.start()   
#time.sleep(3)
t2 = Thread(target=work2)
t2.start()

運(yùn)行結(jié)果:

-work1-num:1105962
-work2-num:1150358

這個(gè)程序是兩個(gè)線程同時(shí)對(duì)全局變量num進(jìn)行相加操作,但是因?yàn)槎嗑€程中線程的執(zhí)行順序是不同的,因此出現(xiàn)最后相加結(jié)果不是2000000的結(jié)果。

示例2:避免全局變量被修改的方法
避免上面的情況可以有很多種方法,第一種是將上面time.sleep(3)的注釋去掉,就是在3秒內(nèi)讓線程1執(zhí)行,3s內(nèi)執(zhí)行完畢再執(zhí)行線程2對(duì)num變量進(jìn)行自增。(不過這種方法跟單線程沒區(qū)別,也就沒有意義去創(chuàng)建多線程了...)

第二種就是使用輪詢,代碼示例如下:

from threading import Thread
import time

num = 0
item = 1

def work1():
    global num
    global item
    if item == 1:
        for i in range(1000000):
            num += 1
        item = 0
    print("-work1-num:%d"%num)

def work2():
    global num
    while True:# 輪詢,一直查看條件是否滿足,線程2一直在執(zhí)行...
        if item != 1:
            for i in range(1000000):
                num += 1
            break
    print("-work2-num:%d"%num)

t1 = Thread(target=work1)
t1.start()
#time.sleep(3)
t2 = Thread(target=work2)
t2.start()

運(yùn)行結(jié)果:

-work1-num:1000000
-work2-num:200000

這次結(jié)果就正確的了,不過這種方法效率也不高。第三種方法就是鎖了。

互斥鎖

當(dāng)多個(gè)線程幾乎同時(shí)修改某一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制
線程同步能夠保證多個(gè)線程安全訪問競(jìng)爭(zhēng)資源,最簡(jiǎn)單的同步機(jī)制是引入互斥鎖。

互斥鎖為資源引入一個(gè)狀態(tài):鎖定/非鎖定
某個(gè)線程要更改共享數(shù)據(jù)時(shí),先將其鎖定,此時(shí)資源的狀態(tài)為“鎖定”,其他線程不能更改;直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源。互斥鎖保證了每次只有一個(gè)線程進(jìn)行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。
threading模塊定義了Lock類,可以很方便地進(jìn)行鎖定。

#創(chuàng)建鎖
mutex = threading.Lock()
#鎖定
mutex.acquire([blocking])
#釋放
mutex.release()

其中,鎖定方法acquire可以有一個(gè)blocking參數(shù)。

如果設(shè)定blocking為True,則當(dāng)前線程會(huì)堵塞,直到獲取到這個(gè)鎖為止(如果沒有指定,那么默認(rèn)為True)

如果設(shè)定blocking為False,則當(dāng)前線程不會(huì)堵

示例:

from threading import Thread,Lock
import time

num = 0

def work1():
    global num
    # 上鎖
    mutex.acquire()   
    for i in range(1000000):
        num += 1
    # 解鎖
    mutex.release()
    print("-work1-num:%d"%num)

def work2():
    global num
    mutex.acquire()
    for i in range(1000000):
        num += 1
    mutex.release()
    print("-work2-num:%d"%num)

# 創(chuàng)建一把鎖,這個(gè)鎖默認(rèn)是沒有上鎖的
mutex = Lock()
t1 = Thread(target=work1)
t1.start()
#time.sleep(3)
t2 = Thread(target=work2)
t2.start()

運(yùn)行結(jié)果:

-work1-num:1000000
-work2-num:2000000

代碼中定義了一把鎖mutex,線程t1和線程t2都互相競(jìng)爭(zhēng)著這把鎖,誰先上鎖,另一方就上不了鎖而堵塞。當(dāng)上鎖的線程執(zhí)行完畢進(jìn)行解鎖,堵塞的線程就爭(zhēng)奪到上鎖權(quán)而進(jìn)行代碼塊的運(yùn)行。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/42956.html

相關(guān)文章

  • Python

    摘要:最近看前端都展開了幾場(chǎng)而我大知乎最熱語言還沒有相關(guān)。有關(guān)書籍的介紹,大部分截取自是官方介紹。但從開始,標(biāo)準(zhǔn)庫為我們提供了模塊,它提供了和兩個(gè)類,實(shí)現(xiàn)了對(duì)和的進(jìn)一步抽象,對(duì)編寫線程池進(jìn)程池提供了直接的支持。 《流暢的python》閱讀筆記 《流暢的python》是一本適合python進(jìn)階的書, 里面介紹的基本都是高級(jí)的python用法. 對(duì)于初學(xué)python的人來說, 基礎(chǔ)大概也就夠用了...

    dailybird 評(píng)論0 收藏0
  • python初學(xué)——網(wǎng)絡(luò)編程FTP服務(wù)器支持多并發(fā)版本

    摘要:擴(kuò)展支持多用戶并發(fā)訪問與線程池。項(xiàng)目請(qǐng)見初學(xué)網(wǎng)絡(luò)編程之服務(wù)器。不允許超過磁盤配額。該文件是一個(gè)使用模塊編寫的線程池類。這一步就做到了線程池的作用。 對(duì)MYFTP項(xiàng)目進(jìn)行升級(jí)。擴(kuò)展支持多用戶并發(fā)訪問與線程池。MYFTP項(xiàng)目請(qǐng)見python初學(xué)——網(wǎng)絡(luò)編程之FTP服務(wù)器。 擴(kuò)展需求 1.在之前開發(fā)的FTP基礎(chǔ)上,開發(fā)支持多并發(fā)的功能2.不能使用SocketServer模塊,必須自己實(shí)現(xiàn)多線...

    oysun 評(píng)論0 收藏0
  • Python - 收藏集 - 掘金

    摘要:首發(fā)于我的博客線程池進(jìn)程池網(wǎng)絡(luò)編程之同步異步阻塞非阻塞后端掘金本文為作者原創(chuàng),轉(zhuǎn)載請(qǐng)先與作者聯(lián)系。在了解的數(shù)據(jù)結(jié)構(gòu)時(shí),容器可迭代對(duì)象迭代器使用進(jìn)行并發(fā)編程篇二掘金我們今天繼續(xù)深入學(xué)習(xí)。 Python 算法實(shí)戰(zhàn)系列之棧 - 后端 - 掘金原文出處: 安生??? 棧(stack)又稱之為堆棧是一個(gè)特殊的有序表,其插入和刪除操作都在棧頂進(jìn)行操作,并且按照先進(jìn)后出,后進(jìn)先出的規(guī)則進(jìn)行運(yùn)作。 如...

    546669204 評(píng)論0 收藏0
  • Python基礎(chǔ)使用期物處理并發(fā)

    摘要:本文重點(diǎn)掌握異步編程的相關(guān)概念了解期物的概念意義和使用方法了解中的阻塞型函數(shù)釋放的特點(diǎn)。一異步編程相關(guān)概念阻塞程序未得到所需計(jì)算資源時(shí)被掛起的狀態(tài)。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之控制流程篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、掌握異步編程的相關(guān)概念;2、了解期物future的概念、意義和使用方法;3、了解Python...

    asoren 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

XboxYan

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<