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

資訊專欄INFORMATION COLUMN

python---協(xié)程

lolomaco / 2585人閱讀

摘要:隨著我們對于效率的追求不斷提高,基于單線程來實現(xiàn)并發(fā)又成為一個新的課題,即只用一個主線程很明顯可利用的只有一個情況下實現(xiàn)并發(fā)。作為的補充可以檢測操作,在遇到操作的情況下才發(fā)生切換協(xié)程介紹協(xié)程是單線程下的并發(fā),又稱微線程,纖程。

引子

之前我們學(xué)習(xí)了線程、進(jìn)程的概念,了解了在操作系統(tǒng)中進(jìn)程是資源分配的最小單位,線程是CPU調(diào)度的最小單位。按道理來說我們已經(jīng)算是把cpu的利用率提高很多了。但是我們知道無論是創(chuàng)建多進(jìn)程還是創(chuàng)建多線程來解決問題,都要消耗一定的時間來創(chuàng)建進(jìn)程、創(chuàng)建線程、以及管理他們之間的切換。
  隨著我們對于效率的追求不斷提高,基于單線程來實現(xiàn)并發(fā)又成為一個新的課題,即只用一個主線程(很明顯可利用的cpu只有一個)情況下實現(xiàn)并發(fā)。這樣就可以節(jié)省創(chuàng)建線進(jìn)程所消耗的時間。
  為此我們需要先回顧下并發(fā)的本質(zhì):切換+保存狀態(tài)
  cpu正在運行一個任務(wù),會在兩種情況下切走去執(zhí)行其他的任務(wù)(切換由操作系統(tǒng)強制控制),一種情況是該任務(wù)發(fā)生了阻塞,另外一種情況是該任務(wù)計算的時間過長

在介紹進(jìn)程理論時,提及進(jìn)程的三種執(zhí)行狀態(tài),而線程才是執(zhí)行單位,所以也可以將上圖理解為線程的三種狀態(tài)
一:其中第二種情況并不能提升效率,只是為了讓cpu能夠雨露均沾,實現(xiàn)看起來所有任務(wù)都被“同時”執(zhí)行的效果,如果多個任務(wù)都是純計算的,這種切換反而會降低效率。
  為此我們可以基于yield來驗證。yield本身就是一種在單線程下可以保存任務(wù)運行狀態(tài)的方法:

1 yiled可以保存狀態(tài),yield的狀態(tài)保存與操作系統(tǒng)的保存線程狀態(tài)很像,但是yield是代碼級別控制的,更輕量級
2 send可以把一個函數(shù)的結(jié)果傳給另外一個函數(shù),以此實現(xiàn)單線程內(nèi)程序之間的切換
#串行執(zhí)行
import time
def consumer(res):
    """任務(wù)1:接收數(shù)據(jù),處理數(shù)據(jù)"""
    pass

def producer():
    """任務(wù)2:生產(chǎn)數(shù)據(jù)"""
    res=[]
    for i in range(10000000):
        res.append(i)
    return res

start=time.time()
#串行執(zhí)行
res=producer()
consumer(res) #寫成consumer(producer())會降低執(zhí)行效率
stop=time.time()
print(stop-start) #1.874000072479248


#基于yield并發(fā)執(zhí)行
import time
def consumer():
    """任務(wù)1:接收數(shù)據(jù),處理數(shù)據(jù)"""
    while True:
        print("this is consumer")
        x=yield

def producer():
    """任務(wù)2:生產(chǎn)數(shù)據(jù)"""
    g=consumer()
    next(g)
    for i in range(10):
        print("this is prodecer")
        g.send(i)

start=time.time()
#基于yield保存狀態(tài),實現(xiàn)兩個任務(wù)直接來回切換,即并發(fā)的效果
#PS:如果每個任務(wù)中都加上打印,那么明顯地看到兩個任務(wù)的打印是你一次我一次,即并發(fā)執(zhí)行的.
producer()

stop=time.time()
print(stop-start) #2.0272178649902344

二:第一種情況的切換。在任務(wù)一遇到io情況下,切到任務(wù)二去執(zhí)行,這樣就可以利用任務(wù)一阻塞的時間完成任務(wù)二的計算,效率的提升就在于此。

import time
def consumer():
    """任務(wù)1:接收數(shù)據(jù),處理數(shù)據(jù)"""
    while True:
        x=yield

def producer():
    """任務(wù)2:生產(chǎn)數(shù)據(jù)"""
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)
        time.sleep(2)

start=time.time()
producer() #并發(fā)執(zhí)行,但是任務(wù)producer遇到io就會阻塞住,并不會切到該線程內(nèi)的其他任務(wù)去執(zhí)行

stop=time.time()
print(stop-start)

對于單線程下,我們不可避免程序中出現(xiàn)io操作,但如果我們能在自己的程序中(即用戶程序級別,而非操作系統(tǒng)級別)控制單線程下的多個任務(wù)能在一個任務(wù)遇到io阻塞時就切換到另外一個任務(wù)去計算,這樣就保證了該線程能夠最大限度地處于就緒態(tài),即隨時都可以被cpu執(zhí)行的狀態(tài),相當(dāng)于我們在用戶程序級別將自己的io操作最大限度地隱藏起來,從而可以迷惑操作系統(tǒng),讓其看到:該線程好像是一直在計算,io比較少,從而更多的將cpu的執(zhí)行權(quán)限分配給我們的線程。

協(xié)程的本質(zhì)就是在單線程下,由用戶自己控制一個任務(wù)遇到io阻塞了就切換另外一個任務(wù)去執(zhí)行,以此來提升效率。為了實現(xiàn)它,我們需要找尋一種可以同時滿足以下條件的解決方案:

1. 可以控制多個任務(wù)之間的切換,切換之前將任務(wù)的狀態(tài)保存下來,以便重新運行時,可以基于暫停的位置繼續(xù)執(zhí)行。
2. 作為1的補充:可以檢測io操作,在遇到io操作的情況下才發(fā)生切換

協(xié)程介紹

協(xié)程:是單線程下的并發(fā),又稱微線程,纖程。英文名Coroutine。一句話說明什么是線程:協(xié)程是一種用戶態(tài)的輕量級線程,即協(xié)程是由用戶程序自己控制調(diào)度的。
需要強調(diào)的是:

1. python的線程屬于內(nèi)核級別的,即由操作系統(tǒng)控制調(diào)度(如單線程遇到io或執(zhí)行時間過長就會被迫交出cpu執(zhí)行權(quán)限,切換其他線程運行)
2. 單線程內(nèi)開啟協(xié)程,一旦遇到io,就會從應(yīng)用程序級別(而非操作系統(tǒng))控制切換,以此來提升效率(!!!非io操作的切換與效率無關(guān))

對比操作系統(tǒng)控制線程的切換,用戶在單線程內(nèi)控制協(xié)程的切換
優(yōu)點如下:

1. 協(xié)程的切換開銷更小,屬于程序級別的切換,操作系統(tǒng)完全感知不到,因而更加輕量級
2. 單線程內(nèi)就可以實現(xiàn)并發(fā)的效果,最大限度地利用cpu

缺點如下:

1. 協(xié)程的本質(zhì)是單線程下,無法利用多核,可以是一個程序開啟多個進(jìn)程,每個進(jìn)程內(nèi)開啟多個線程,每個線程內(nèi)開啟協(xié)程
2. 協(xié)程指的是單個線程,因而一旦協(xié)程出現(xiàn)阻塞,將會阻塞整個線程

總結(jié)協(xié)程特點:

1.必須在只有一個單線程里實現(xiàn)并發(fā)
2.修改共享數(shù)據(jù)不需加鎖
3.用戶程序里自己保存多個控制流的上下文棧
4.一個協(xié)程遇到IO操作自動切換到其它協(xié)程(如何實現(xiàn)檢測IO,yield、greenlet都無法實現(xiàn),就用到了gevent模塊(select機(jī)制))   
Gevent模塊

安裝:pip3 install gevent
Gevent 是一個第三方庫,可以輕松通過gevent實現(xiàn)并發(fā)同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴(kuò)展模塊形式接入Python的輕量級協(xié)程。 Greenlet全部運行在主程序操作系統(tǒng)進(jìn)程的內(nèi)部,但它們被協(xié)作式地調(diào)度。
用法介紹

g1=gevent.spawn(func,1,,2,3,x=4,y=5)創(chuàng)建一個協(xié)程對象g1,spawn括號內(nèi)第一個參數(shù)是函數(shù)名,
如eat,后面可以有多個參數(shù),可以是位置實參或關(guān)鍵字實參,都是傳給函數(shù)eat的

g2=gevent.spawn(func2)

g1.join() #等待g1結(jié)束

g2.join() #等待g2結(jié)束

#或者上述兩步合作一步:gevent.joinall([g1,g2])

g1.value#拿到func1的返回值

例:遇到io主動切換

import gevent
def eat(name):
    print("%s eat 1" %name)
    gevent.sleep(2)
    print("%s eat 2" %name)

def play(name):
    print("%s play 1" %name)
    gevent.sleep(1)
    print("%s play 2" %name)


g1=gevent.spawn(eat,"egon")
g2=gevent.spawn(play,"egon")
g1.join()
g2.join()
#或者gevent.joinall([g1,g2])
print("主")

上例gevent.sleep(2)模擬的是gevent可以識別的io阻塞,而time.sleep(2)或其他的阻塞,gevent是不能直接識別的需要用下面一行代碼,打補丁,就可以識別了

from gevent import monkey;monkey.patch_all()必須放到被打補丁者的前面,如time,socket模塊之前

或者我們干脆記憶成:要用gevent,需要將from gevent import monkey;monkey.patch_all()放到文件的開頭

from gevent import monkey;monkey.patch_all()

import gevent
import time
def eat():
    print("eat food 1")
    time.sleep(2)
    print("eat food 2")

def play():
    print("play 1")
    time.sleep(1)
    print("play 2")

g1=gevent.spawn(eat)
g2=gevent.spawn(play)
gevent.joinall([g1,g2])
print("主")

我們可以用threading.current_thread().getName()來查看每個g1和g2,查看的結(jié)果為DummyThread-n,即假線程

from gevent import monkey;monkey.patch_all()
import threading
import gevent
import time
def eat():
    print(threading.current_thread().getName())
    print("eat food 1")
    time.sleep(2)
    print("eat food 2")

def play():
    print(threading.current_thread().getName())
    print("play 1")
    time.sleep(1)
    print("play 2")

g1=gevent.spawn(eat)
g2=gevent.spawn(play)
gevent.joinall([g1,g2])
print("主")
Gevent之同步與異步
from gevent import spawn, joinall, monkey;monkey.patch_all()
import time
def task(pid):
    """
    Some non-deterministic task
    """
    time.sleep(0.5)
    print("Task %s done" % pid)


def synchronous():  # 同步
    for i in range(10):
        task(i)
def asynchronous():  # 異步
    g_l = [spawn(task, i) for i in range(10)]
    joinall(g_l)
    print("DONE")
if __name__ == "__main__":
    print("Synchronous:")
    synchronous()
    print("Asynchronous:")
    asynchronous()
#  上面程序的重要部分是將task函數(shù)封裝到Greenlet內(nèi)部線程的gevent.spawn。
#  初始化的greenlet列表存放在數(shù)組threads中,此數(shù)組被傳給gevent.joinall 函數(shù),
#  后者阻塞當(dāng)前流程,并執(zhí)行所有給定的greenlet任務(wù)。執(zhí)行流程只會在 所有g(shù)reenlet執(zhí)行完后才會繼續(xù)向下走。
協(xié)程socket
from gevent import monkey;monkey.patch_all()
import socket
import gevent

def talk(conn):
    while True:
        conn.send(b"hello")
        print(conn.recv(1024))

sk = socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()

while True:
    conn,addr = sk.accept()
    g = gevent.spawn(talk,conn)

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/42185.html

相關(guān)文章

  • Python協(xié)程(真才實學(xué),想學(xué)的進(jìn)來)

    摘要:所以與多線程相比,線程的數(shù)量越多,協(xié)程性能的優(yōu)勢越明顯。值得一提的是,在此過程中,只有一個線程在執(zhí)行,因此這與多線程的概念是不一樣的。 真正有知識的人的成長過程,就像麥穗的成長過程:麥穗空的時候,麥子長得很快,麥穗驕傲地高高昂起,但是,麥穗成熟飽滿時,它們開始謙虛,垂下麥芒。 ——蒙田《蒙田隨筆全集》 上篇論述了關(guān)于python多線程是否是雞肋的問題,得到了一些網(wǎng)友的認(rèn)可,當(dāng)然也有...

    lykops 評論0 收藏0
  • 異步等待的 Python 協(xié)程

    摘要:輔之以事件循環(huán),協(xié)程可用于異步處理,尤其是在中。當(dāng)前支持的協(xié)程基于增強型生成器,于版本開始采用。新的特性中,異步還有兩種新用途異步內(nèi)容管理器和迭代器。 現(xiàn)在 Python 已經(jīng)支持用協(xié)程進(jìn)行異步處理。但最近有建議稱添加協(xié)程以全面完善 Python 的語言結(jié)構(gòu),而不是像現(xiàn)在這樣把他們作為生成器的一個類型。此外,兩個新的關(guān)鍵字———異步(async)和等待(await),都該添加到 Pyt...

    NicolasHe 評論0 收藏0
  • python協(xié)程與golang協(xié)程的區(qū)別

    摘要:進(jìn)程線程和協(xié)程進(jìn)程的定義進(jìn)程,是計算機(jī)中已運行程序的實體。協(xié)程和線程的關(guān)系協(xié)程是在語言層面實現(xiàn)對線程的調(diào)度,避免了內(nèi)核級別的上下文消耗。和都引入了消息調(diào)度系統(tǒng)模型,來避免鎖的影響和進(jìn)程線程開銷大的問題。 進(jìn)程、線程和協(xié)程 進(jìn)程的定義: 進(jìn)程,是計算機(jī)中已運行程序的實體。程序本身只是指令、數(shù)據(jù)及其組織形式的描述,進(jìn)程才是程序的真正運行實例。 線程的定義: 操作系統(tǒng)能夠進(jìn)行運算調(diào)度的最小單...

    csRyan 評論0 收藏0
  • python基礎(chǔ)教程:異步IO 之編程例子

    摘要:創(chuàng)建第一個協(xié)程推薦使用語法來聲明協(xié)程,來編寫異步應(yīng)用程序。協(xié)程兩個緊密相關(guān)的概念是協(xié)程函數(shù)通過定義的函數(shù)協(xié)程對象調(diào)用協(xié)程函數(shù)返回的對象。它是一個低層級的可等待對象,表示一個異步操作的最終結(jié)果。 我們講以Python 3.7 上的asyncio為例講解如何使用Python的異步IO。 showImg(https://segmentfault.com/img/remote/14600000...

    wangxinarhat 評論0 收藏0
  • python大佬養(yǎng)成計劃----協(xié)程

    摘要:協(xié)程,又稱微線程,纖程。最大的優(yōu)勢就是協(xié)程極高的執(zhí)行效率。生產(chǎn)者產(chǎn)出第條數(shù)據(jù)返回更新值更新消費者正在調(diào)用第條數(shù)據(jù)查看當(dāng)前進(jìn)行的線程函數(shù)中有,返回值為生成器庫實現(xiàn)協(xié)程通過提供了對協(xié)程的基本支持,但是不完全。 協(xié)程,又稱微線程,纖程。英文名Coroutine協(xié)程看上去也是子程序,但執(zhí)行過程中,在子程序內(nèi)部可中斷,然后轉(zhuǎn)而執(zhí)行別的子程序,在適當(dāng)?shù)臅r候再返回來接著執(zhí)行。 最大的優(yōu)勢就是協(xié)程極高...

    svtter 評論0 收藏0
  • 談?wù)?em>Python協(xié)程技術(shù)的演進(jìn)

    摘要:事件循環(huán)是異步編程的底層基石。對事件集合進(jìn)行輪詢,調(diào)用回調(diào)函數(shù)等一輪事件循環(huán)結(jié)束,循環(huán)往復(fù)。協(xié)程直接利用代碼的執(zhí)行位置來表示狀態(tài),而回調(diào)則是維護(hù)了一堆數(shù)據(jù)結(jié)構(gòu)來處理狀態(tài)。時代的協(xié)程技術(shù)主要是,另一個比較小眾。 Coding Crush Python開發(fā)工程師 主要負(fù)責(zé)豈安科技業(yè)務(wù)風(fēng)險情報系統(tǒng)redq。 引言 1.1. 存儲器山 存儲器山是 Randal Bryant 在《深入...

    zhiwei 評論0 收藏0

發(fā)表評論

0條評論

lolomaco

|高級講師

TA的文章

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