python程式設計使用協程併發的優缺點

2021-09-14 01:30:39 字數 3018 閱讀 5495

開發十年,就只剩下這套架構體系了! >>>

協程是一種使用者態的輕量級執行緒,又稱微執行緒。

協程擁有自己的暫存器上下文和棧,排程切換時,將暫存器上下文和棧儲存到其他地方,>在切回來的時候,恢復先前儲存的暫存器上下文和棧。因此:協程能保留上一次呼叫時的》狀態(即所有區域性狀態的乙個特定組合),每次過程重入時,就相當於進入上一次呼叫的》狀態,換種說法:進入上一次離開時所處邏輯流的位置.

所謂原子操作是指不會被執行緒排程機制打斷的操作;這種操作一旦開始,就一直執行到結束,中間不會有任何 context switch (切換到另乙個執行緒)。原子操作可以是乙個步驟,也可以是多個操作步驟,但是其順序是不可以被打亂,或者切割掉只執行部分。視作整體是原子性的核心

gevent是python的乙個併發框架,以微執行緒greenlet為核心,使用了epoll事件監聽機制以及諸多其他優化而變得高效.

gevent的sleep可以交出控制權,當我們在受限於網路或io的函式中使用gevent,這些函式會被協作式的排程, gevent的真正能力會得到發揮。gevent處理了所有的細節, 來保證你的網路庫會在可能的時候,隱式交出greenlet上下文的執行權

import gevent

def foo():

print('running in foo')

gevent.sleep(0)

print('com back from bar in to foo')

def bar():

print('running in bar')

gevent.sleep(0)

print('com back from foo in to bar')

# 建立執行緒並行執行程式

gevent.joinall([

gevent.spawn(foo),

gevent.spawn(bar),

])# 執行結果:

#running in foo

#running in bar

#com back from bar in to foo

#com back from foo in to bar

import random

import gevent

def task(pid):

gevent.sleep(random.randint(0, 2) * 0.001)

print('task %s done' % pid)

def synchronous():

for i in range(1, 10):

task(i)

def asynchronous():

threads = [gevent.spawn(task, i) for i in range(10)]

gevent.joinall(threads)

print('synchronous:')

synchronous()

print('asynchronous:')

asynchronous()

可以子類化greenlet類,過載它的_run方法,類似多線執行緒和多程序模組

import gevent

from gevent import greenlet

class test(greenlet):

def __init__(self, message, n):

greenlet.__init__(self)

self.message = message

self.n = n

def _run(self):

print(self.message, 'start')

gevent.sleep(self.n)

print(self.message, 'end')

tests = [

test("hello", 3),

test("world", 2),

]for test in tests:

test.start() # 啟動

for test in tests:

test.join() # 等待執行結束

當乙個greenlet遇到io操作時,比如訪問網路,就自動切換到其他的greenlet,等到io操作完成,再在適當的時候切換回來繼續執行。

由於io操作非常耗時,經常使程式處於等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在執行,而不是等待io。

由於切換是在io操作時自動完成,所以gevent需要修改python自帶的一些標準庫,這一過程在啟動時通過monkey patch完成

import gevent

import requests

from gevent import monkey

monkey.patch_socket()

def task(url):

r = requests.get(url)

print('%s bytes received from %s' % (len(r.text), url))

gevent.joinall([

gevent.spawn(task, ''),

gevent.spawn(task, ''),

gevent.spawn(task, ''),

])

執行輸出

2443 bytes received from 

108315 bytes received from

231873 bytes received from

可以看出3個網路操作是併發執行的,而且結束順序不同

python 併發程式設計 協程 協程介紹

協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的 需要強調的是 1.python的執行緒屬於核心級別的,即由作業系統控制排程 如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可...

Python 併發程式設計(協程)

本章節主要介紹,使用單執行緒實現併發,即只用乙個主線程 很明顯可利用cpu只有乙個 為此我們需要先回顧下併發的本質 切換 儲存狀態 ps 在介紹程序理論時,提及程序的三種執行狀態,而執行緒才是執行單位,所以也可以將上圖理解為執行緒的三種狀態 單執行緒下併發稱為 協程 特點 缺點 gevent 是乙個...

併發程式設計 協程

一 協程介紹 協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。需要強調的是 對比作業系統控制線程的切換,使用者在單執行緒內控制協程的切換 優點如下 缺點如下 總結 必須在只有乙個單執...