協程:是單執行緒下的併發,一句話說明什麼是執行緒:協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。
對比作業系統控制線程的切換,使用者在單執行緒內控制協程的切換
優點:
#缺點:1. 協程的切換開銷更小,屬於程式級別的切換,作業系統完全感知不到,因而更加輕量級
#2. 單執行緒內就可以實現併發的效果,最大限度地利用cpu
#總結協程特點:1. 協程的本質是單執行緒下,無法利用多核,可以是乙個程式開啟多個程序,每個程序內開啟多個執行緒,每個執行緒內開啟協程
#2. 協程指的是單個執行緒,因而一旦協程出現阻塞,將會阻塞整個執行緒
1、必須在只有乙個單執行緒裡實現併發
2、修改共享資料不需加鎖
3、使用者程式裡自己儲存多個控制流的上下文棧
4、附加:乙個協程遇到io操作自動切換到其它協程(如何實現檢測io,yield、greenlet都無法實現,就用到了gevent模組(select機制))
協程的實現:
import應用場景:time
deftask():
while
true:
print("
task1")
time.sleep(4)
yield 1
deftask2():
g =task()
while
true:
try:
print("
task2")
next(g)
except
exception:
print("
任務完成")
break
task2()
tcp 多客戶端實現方式1.來乙個客戶端就來乙個程序 資源消耗較大
2.來乙個客戶端就來乙個執行緒 也不能無限開
3.用程序池 或 執行緒池 還是乙個執行緒或程序只能維護乙個連線
4.協程 乙個執行緒就可以處理多個客戶端 遇到io就切到另乙個
importgreenlet只是提供了一種比generator更加便捷的切換方式,當切到乙個任務執行時如果遇到io,那就原地阻塞,仍然是沒有解決遇到io自動切換來提公升效率的問題。greenlet
import
time
deftask1():
print("
task1 1")
time.sleep(2)
g2.switch()
print("
task1 2")
g2.switch()
deftask2():
print("
task2 1")
g1.switch()
print("
task2 2")
g1 =greenlet.greenlet(task1)
g2 =greenlet.greenlet(task2)
g1.switch()
#1.例項化greenlet得到乙個物件 傳入要執行的任務
#至少需要兩個任務
#2.先讓某個任務執行起來 使用物件呼叫switch
#3.在任務的執行過程中 手動呼叫switch來切換
單執行緒裡的多個任務的**通常會既有計算操作又有阻塞操作,我們完全可以在執行任務1時遇到阻塞,就利用阻塞的時間去執行任務2。。。。如此,才能提高效率,這就用到了gevent模組。
gevent 是乙個第三方庫,可以輕鬆通過gevent實現併發同步或非同步程式設計,在gevent中用到的主要模式是greenlet, 它是以c擴充套件模組形式接入python的輕量級協程。 greenlet全部執行在主程式作業系統程序的內部,但它們被協作式地排程。
from gevent import練習:使用協程完成tcp套接字程式設計 支援多客戶端同時訪問monkey
monkey.patch_all()
import
gevent
import
time
defeat():
print('
eat food 1')
time.sleep(2)
#gevent.sleep(1)
print('
eat food 2')
defplay():
print('
play 1')
time.sleep(1)
#gevent.sleep(1)
print('
play 2')
g1=gevent.spawn(eat)
g2=gevent.spawn(play)
#g1.join()
#g2.join()
gevent.joinall([g1,g2])
print('主'
)#1.spawn函式傳入你的任務
#2.呼叫join 去開啟任務
#3.檢測io操作需要打monkey補丁 就是乙個函式 在程式最開始的地方呼叫它
import伺服器gevent
from gevent import
monkey
monkey.patch_all()
import
socket
server =socket.socket()
#重用埠
server.setsockopt(socket.sol_socket,socket.so_reuseaddr,1)
server.bind((
"127.0.0.1
",9999))
server.listen(5)
defdata_handler(conn):
print("
乙個新連線..")
while
true:
data = conn.recv(1024)
conn.send(data.upper())
while
true:
conn,addr =server.accept()
#切到處理資料的任務去執行
gevent.spawn(data_handler,conn)
import客戶端socket
c =socket.socket()
c.connect((
"127.0.0.1
",9999))
while
true:
msg = input("
>>>:")
ifnot msg:continue
c.send(msg.encode(
"utf-8"))
data = c.recv(1024)
print(data.decode("
utf-8
"))
併發程式設計之 協程
程序 資源單位 執行緒 執行單位 協程 單執行緒下實現併發 併發 切換 儲存狀態 程式設計師自己通過 自己檢測程式中的io 一旦遇到了io自己通過 切換 給作業系統的感覺就是你這個執行緒沒有任何的io 從而提公升 的執行效率 切換 儲存狀態一定能夠提公升效率嗎?1.當任務是io密集型的情況下 提公升...
Python 之併發程式設計之協程
def gen for i in range 10 yield i 初始化生成七函式 返回生成器物件 簡稱生成器 mygen gen for i in mygen print i 1 用協程改寫成生產者消費者 def producer for i in range 100 yield i def c...
併發程式設計 協程
一 協程介紹 協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。需要強調的是 對比作業系統控制線程的切換,使用者在單執行緒內控制協程的切換 優點如下 缺點如下 總結 必須在只有乙個單執...