国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python系統編程之線程

XboxYan / 2045人閱讀

摘要:可以將它們認為是在一個主進程或主線程中并行運行的一些迷你進程。因此與進程相比,線程之間的信息共享和通信更加容易。當上鎖的線程執行完畢進行解鎖,堵塞的線程就爭奪到上鎖權而進行代碼塊的運行。

threading模塊 線程簡述

線程(輕量級進程)與進程類似,不過它們是在同一個進程下執行的,并共享相同的上下文??梢詫⑺鼈冋J為是在一個主進程或"主線程"中并行運行的一些"迷你進程"。

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

多線程的創建

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

創建Thread的示例,傳給它一個函數;

派生Thread的子類,重新run方法,并創建子類的實例。

示例1:創建Thread的實例,傳給它一個函數

from threading import Thread
import time

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


for i in range(5):
    #創建線程,線程執行的任務是target指定的函數,如果函數需要傳入參數,則可以指定args=(),或者kwargs={}
    t = Thread(target=test)
    t.start()

運行結果:

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

示例2:使用Thread子類創建線程

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__":
    # 創建線程
    t = myThread()
    t.start()

運行結果:

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

python的threading.Thread類有一個run方法,用于定義線程的功能函數,可以在自己的線程類中覆蓋該方法。而創建自己的線程實例后,通過Thread類的start方法,可以啟動該線程,交給python虛擬機進行調度,當該線程獲得執行的機會時,就會調用run方法執行線程。

多線程共享全局變量

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

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執行完畢。
time.sleep(1)
t2 = Thread(target=thread2)
t2.start()

運行結果:

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

線程關于全局變量注意點
在一個進程內的所有線程共享全局變量,能夠在不適用其他方式的前提下完成多線程之間的數據共享(這點要比多進程要好)

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

當然,這種共享是有風險的。如果兩個或多個線程訪問同一片數據,由于數據的訪問順序不同可能導致結果不一致。這種情況叫競態條件。辛運的是,大多數線程庫都有一些同步源語,以允許線程管理器控制執行和訪問。

同步和互斥鎖 同步

一般在多線程代碼中,總有一些函數或者代碼塊不希望被多個線程同時執行,如果有兩個線程運行的順序發生變化,就有可能造成代碼的執行軌跡或行為不同,產生不一樣的數據。這時候就需要使用同步了。

同步可以理解為協同步調,按預定的先后次序進行運行,比如你先說,我再講。

示例1:多個線程對全局變量修改的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()

運行結果:

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

這個程序是兩個線程同時對全局變量num進行相加操作,但是因為多線程中線程的執行順序是不同的,因此出現最后相加結果不是2000000的結果。

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

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

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一直在執行...
        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()

運行結果:

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

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

互斥鎖

當多個線程幾乎同時修改某一個共享數據的時候,需要進行同步控制
線程同步能夠保證多個線程安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。

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

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

其中,鎖定方法acquire可以有一個blocking參數。

如果設定blocking為True,則當前線程會堵塞,直到獲取到這個鎖為止(如果沒有指定,那么默認為True)

如果設定blocking為False,則當前線程不會堵

示例:

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)

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

運行結果:

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

代碼中定義了一把鎖mutex,線程t1和線程t2都互相競爭著這把鎖,誰先上鎖,另一方就上不了鎖而堵塞。當上鎖的線程執行完畢進行解鎖,堵塞的線程就爭奪到上鎖權而進行代碼塊的運行。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42956.html

相關文章

  • Python

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

    dailybird 評論0 收藏0
  • python初學——網絡編程FTP服務器支持多并發版本

    摘要:擴展支持多用戶并發訪問與線程池。項目請見初學網絡編程之服務器。不允許超過磁盤配額。該文件是一個使用模塊編寫的線程池類。這一步就做到了線程池的作用。 對MYFTP項目進行升級。擴展支持多用戶并發訪問與線程池。MYFTP項目請見python初學——網絡編程之FTP服務器。 擴展需求 1.在之前開發的FTP基礎上,開發支持多并發的功能2.不能使用SocketServer模塊,必須自己實現多線...

    oysun 評論0 收藏0
  • Python - 收藏集 - 掘金

    摘要:首發于我的博客線程池進程池網絡編程之同步異步阻塞非阻塞后端掘金本文為作者原創,轉載請先與作者聯系。在了解的數據結構時,容器可迭代對象迭代器使用進行并發編程篇二掘金我們今天繼續深入學習。 Python 算法實戰系列之棧 - 后端 - 掘金原文出處: 安生??? 棧(stack)又稱之為堆棧是一個特殊的有序表,其插入和刪除操作都在棧頂進行操作,并且按照先進后出,后進先出的規則進行運作。 如...

    546669204 評論0 收藏0
  • Python基礎使用期物處理并發

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

    asoren 評論0 收藏0

發表評論

0條評論

XboxYan

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<