1. 程式人生 > >Goroutine(協程)為何能處理大併發

Goroutine(協程)為何能處理大併發

簡單來說:協程十分輕量,可以在一個程序中執行有數以十萬計的協程,依舊保持高效能。

程序、執行緒、協程的關係和區別:

  • 程序擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,程序由作業系統排程。

  • 執行緒擁有自己獨立的棧和共享的堆,共享堆,不共享棧,執行緒亦由作業系統排程(標準執行緒是的)。

  • 協程和執行緒一樣共享堆,不共享棧,協程由程式設計師在協程的程式碼裡顯示排程。

協程和執行緒的區別是:協程避免了無意義的排程,由此可以提高效能,但也因此,程式設計師必須自己承擔排程的責任。

執行協程只需要極少的棧記憶體(大概是4~5KB),預設情況下,執行緒棧的大小為1MB。

goroutine就是一段程式碼,一個函式入口,以及在堆上為其分配的一個堆疊。所以它非常廉價,我們可以很輕鬆的建立上萬個goroutine,但它們並不是被作業系統所排程執行。

和所有其他併發框架裡的協程一樣,goroutine裡所謂“無鎖”的優點只在單執行緒下有效,如果$GOMAXPROCS > 1並且協程間需要通訊,Go執行庫會負責加鎖保護資料,這也是為什麼sieve.go這樣的例子在多CPU多執行緒時反而更慢的原因.

goroutine 的一個主要特性就是它們的消耗;建立它們的初始記憶體成本很低廉(與需要 1 至 8MB 記憶體的傳統 POSIX 執行緒形成鮮明對比)以及根據需要動態增長和縮減佔用的資源。這使得 goroutine 會從 4096 位元組的初始棧記憶體佔用開始按需增長或縮減記憶體佔用,而無需擔心資源的耗盡。

為了實現這個目標,連結器(5l、6l 和 8l)會在每個函式前插入一個序文,這個序文會在函式被呼叫之前檢查判斷當前的資源是否滿足呼叫該函式的需求(備註 1)。如果不滿足,則呼叫 runtime.morestack 來分配新的棧頁面(備註 2),從函式的呼叫者那裡拷貝函式的引數,然後將控制權返回給呼叫者。此時,已經可以安全地呼叫該函數了。當函式執行完畢,事情並沒有就此結束,函式的返回引數又被拷貝至呼叫者的棧結構中,然後釋放無用的棧空間。

通過這個過程,有效地實現了棧記憶體的無限使用。假設你並不是不斷地在兩個棧之間往返,通俗地講叫棧分割,則代價是十分低廉的。

參考資料:

相關推薦

Goroutine為何處理併發

簡單來說:協程十分輕量,可以在一個程序中執行有數以十萬計的協程,依舊保持高效能。 程序、執行緒、協程的關係和區別: 程序擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,程序由作業系統排程。 執行緒擁有自己獨立的棧和共享的堆,共享堆,不共享棧,執行緒亦由作業系統排程(標準執行緒是的)。 協程和執行緒一

生成器和生成器並行

a+b () 當前 break sleep exce pro con true import time#列表生成式 t=[i*2 for i in range(10)] print(t) print(t[8]) 生成器:只有在調用的時候生成相應的數據,一種算法。 #只記住當

python 學習第二十五天

協程 協程,又稱微執行緒,纖程。英文名Coroutine。 優點1: 協程極高的執行效率。因為子程式切換不是執行緒切換,而是由程式自身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的效能優勢就越明顯。 優點2: 不需要多執行緒的鎖機制,因為只有一個執行緒,

Python-greenlet完成多工代替yield,使用gevent完成多工

 gevent 實現多工: import gevent # 遇到延時就切換任務 def f1(n): for i in range(n): print(gevent.getcurrent(), i) gevent.sleep(0.5) # 必須用

C#中的yield return與Unity中的Coroutine

C#中的yield return C#語法中有個特別的關鍵字yield, 它是幹什麼用的呢? 來看看專業的解釋: yield 是在迭代器塊中用於向列舉數物件提供值或發出迭代結束訊號。它的形式為下列之一:yield return <expression>;yield break 看如下例

go核心chan.go檔案分析解讀go是如何排程通道內容

回顧 上文我們分析到了,golang是如何產生一個通道的。 其實很簡單,就像所有的高階語言一樣,我宣告並實現一個物件(雖然go裡不

重修課程day35網絡編九之

__name__ accept multi 使用 port socket produce 阻塞 優缺點 什麽是用戶態和內核態:  內核態:當一個任務(進程)執行系統調用而陷入了內核代碼中執行,這就叫做內核態。  用戶態:當用戶在執行自己的代碼時,這就叫在用戶態   內核態和

python-gevent模塊自動切換io的

UNC TE fun AS imp In 程序 自動 AR import gevent def foo(): print("Running in foo") gevent.sleep(2) print("Explicit context sw

異步IO,消息循環隊列

http框架 for 例如 高並發 bsp 標識 類型 tex 請求 同步是CPU自己主動查看IO操作是否完成,異步是IO操作完成後發出信號通知CPU(CPU是被通知的) 阻塞與非阻塞的區別在於發起IO操作之後,CPU是等待IO操作完成再進行下一步操作,還是不等待去做其他的

Python_並發編

eating oba ive 程序 setname rod 執行過程 生產者消費者模式 random 一、進程和線程 進程 進程就是一個程序在一個數據集上的一次動態執行過程。 進程一般由程序、數據集、進程控制塊三部分組成。我們編寫的程序用來描述進程要完成哪些功能以及如何完

、線

生成 next 進程 true code 語言 one pytho 返回 什麽是協程?   首先,先說一個前提:子程序/函數:在所有語言中都是層級調用的,比如A調用B。在B執行過程中又可以調用C,C執行完畢返回,B執行完畢返回,最後是A執行完畢返回。是通過棧實現的,一個線程

程序、執行緒、

什麼是協程? 首先,先說一個前提:子程式/函式:在所有語言中都是層級呼叫的,比如A呼叫B。在B執行過程中又可以呼叫C,C執行完畢返回,B執行完畢返回,最後是A執行完畢返回。是通過棧實現的,一個執行緒就是執行一個子程式,子程式呼叫總是一個入口,一次返回,呼叫的順序是明確的。

01-實現多執行緒切換和排程實驗介紹原理

本系列文章旨在記錄完成一個小型使用者級執行緒建立、切換與排程框架的過程,並不能代替作業系統為我們提供的執行緒框架。 為什麼要寫這樣的東西呢?目的很簡單,僅僅在於學習作業系統中的程序或執行緒切換與排程原理。所以,請不要把程式碼試圖用到你的工程或者專案中,出了問題

Swoole 實戰:MySQL 查詢器的實現連線池版

[toc] ### 需求分析 本篇我們將通過 Swoole 實現一個自帶連線池的 MySQL 查詢器: 1. 支援通過鏈式呼叫構造並執行 SQL 語句; 2. 支援連線池技術; 3. 支援多協程事務併發執行(協程安全性); 4. 支援連線物件的健康檢測; 5. 支援連線物件斷線重連; 6. 程式需要可擴充套件

linux雲自動化運維基礎知識7

linux####1.進程定義####進程就是cpu未完成的工作####2.ps命令####ps a ##關於當前環境的所有進程 x| -A ##所有進程 f ##顯示進程從屬關系 e ##顯示進程調用環境工具的詳細信息 l ##長列表顯示進程的詳細

Thread

toa mage name 事件 turn *** line 其他 edt 今天我們繼續接著線程講講,上一章提到一下task概念, 首先接著task繼續往下講,在前章節提到過Thread怎麽實現其他線程完成後再讓主線程繼續執行的功能,那麽如果Task也需要線程等待事件,該怎

python制作wifi破解跑字典單線

imp disco 初始化 read clas rds name () link 很雞巴簡單,接上一篇文章 import pywifi import sys import time from pywifi import const def test_wifi_conne

python學習筆記二十:異常處理

錯誤 fetchall nbsp 如果 info blog months api root 1 def calc(a,b): 2 res=a/b 3 return res 4 def main(): 5 money=input(‘輸入多少

數據庫性優化database tuning優化絕不僅僅只是索引

節點 故障 XP 邏輯 而已 postgresq 適用場景 數據 整體 一畢業就接觸優化方面的問題,專業做優化也有至少5年之多的時間了,可現在還是經常聽到很多人認為優化很簡單,就是建索引的問題,這確實不能怪大家,做這行20多年的時間裏,在職業生涯的每個階段,幾乎都能聽到這樣

MSSQL數據庫後臺進

也會 完成 磁盤 xtend handle 導致 inner sql數據庫 使用 與Oracle數據庫類似,微軟數據庫產品MSSQL也有諸多後臺進程來保證數據庫系統的高效正常運轉,由於MSSQL采用的是線程模型,應該叫做後臺線程,為了大家易於理解,我們在暫且稱之為後臺進程,