日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go 怎么等待所有的协程完成_GO语言基础进阶教程:Go语言的协程——Goroutine

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go 怎么等待所有的协程完成_GO语言基础进阶教程:Go语言的协程——Goroutine 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Go語言的協程——Goroutine

進程(Process),線程(Thread),協程(Coroutine,也叫輕量級線程)

進程進程是一個程序在一個數據集中的一次動態執行過程,可以簡單理解為“正在執行的程序”,它是CPU資源分配和調度的獨立單位。 進程一般由程序、數據集、進程控制塊三部分組成。我們編寫的程序用來描述進程要完成哪些功能以及如何完成;數據集則是程序在執行過程中所需要使用的資源;進程控制塊用來記錄進程的外部特征,描述進程的執行變化過程,系統可以利用它來控制和管理進程,它是系統感知進程存在的唯一標志。 進程的局限是創建、撤銷和切換的開銷比較大。

線程線程是在進程之后發展出來的概念。 線程也叫輕量級進程,它是一個基本的CPU執行單元,也是程序執行過程中的最小單元,由線程ID、程序計數器、寄存器集合和堆棧共同組成。一個進程可以包含多個線程。 線程的優點是減小了程序并發執行時的開銷,提高了操作系統的并發性能,缺點是線程沒有自己的系統資源,只擁有在運行時必不可少的資源,但同一進程的各線程可以共享進程所擁有的系統資源,如果把進程比作一個車間,那么線程就好比是車間里面的工人。不過對于某些獨占性資源存在鎖機制,處理不當可能會產生“死鎖”。

協程協程是一種用戶態的輕量級線程,又稱微線程,英文名Coroutine,協程的調度完全由用戶控制。人們通常將協程和子程序(函數)比較著理解。 子程序調用總是一個入口,一次返回,一旦退出即完成了子程序的執行。

與傳統的系統級線程和進程相比,協程的最大優勢在于其"輕量級",可以輕松創建上百萬個而不會導致系統資源衰竭,而線程和進程通常最多也不能超過1萬的。這也是協程也叫輕量級線程的原因。

協程的特點在于是一個線程執行,與多線程相比,其優勢體現在:協程的執行效率極高。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。

Goroutine

1.1 什么是Goroutine

go中使用Goroutine來實現并發concurrently。

Goroutine是Go語言特有的名詞。區別于進程Process,線程Thread,協程Coroutine,因為Go語言的創造者們覺得和他們是有所區別的,所以專門創造了Goroutine。

Goroutine是與其他函數或方法同時運行的函數或方法。Goroutines可以被認為是輕量級的線程。與線程相比,創建Goroutine的成本很小,它就是一段代碼,一個函數入口。以及在堆上為其分配的一個堆棧(初始大小為4K,會隨著程序的執行自動增長刪除)。因此它非常廉價,Go應用程序可以并發運行數千個Goroutines。

Goroutines在線程上的優勢。
  • 與線程相比,Goroutines非常便宜。它們只是堆棧大小的幾個kb,堆??梢愿鶕贸绦虻男枰鲩L和收縮,而在線程的情況下,堆棧大小必須指定并且是固定的
  • Goroutines被多路復用到較少的OS線程。在一個程序中可能只有一個線程與數千個Goroutines。如果線程中的任何Goroutine都表示等待用戶輸入,則會創建另一個OS線程,剩下的Goroutines被轉移到新的OS線程。所有這些都由運行時進行處理,我們作為程序員從這些復雜的細節中抽象出來,并得到了一個與并發工作相關的干凈的API。
  • 當使用Goroutines訪問共享內存時,通過設計的通道可以防止競態條件發生。通道可以被認為是Goroutines通信的管道。
  • 1.2 主goroutine

    封裝main函數的goroutine稱為主goroutine。

    主goroutine所做的事情并不是執行main函數那么簡單。它首先要做的是:設定每一個goroutine所能申請的棧空間的最大尺寸。在32位的計算機系統中此最大尺寸為250MB,而在64位的計算機系統中此尺寸為1GB。如果有某個goroutine的??臻g尺寸大于這個限制,那么運行時系統就會引發一個棧溢出(stack overflow)的運行時恐慌。隨后,這個go程序的運行也會終止。

    此后,主goroutine會進行一系列的初始化工作,涉及的工作內容大致如下:

  • 創建一個特殊的defer語句,用于在主goroutine退出時做必要的善后處理。因為主goroutine也可能非正常的結束
  • 啟動專用于在后臺清掃內存垃圾的goroutine,并設置GC可用的標識
  • 執行mian包中的init函數
  • 執行main函數
    執行完main函數后,它還會檢查主goroutine是否引發了運行時恐慌,并進行必要的處理。最后主goroutine會結束自己以及當前進程的運行。
  • 1.3 如何使用Goroutines

    在函數或方法調用前面加上關鍵字go,您將會同時運行一個新的Goroutine。

    實例代碼:

    package main ? import ( "fmt" ) ? func hello() { fmt.Println("Hello world goroutine") } func main() { go hello()fmt.Println("main function") }

    運行結果:可能會值輸出“main function”。

    我們開始的Goroutine怎么樣了?我們需要了解Goroutine的規則

  • 當新的Goroutine開始時,Goroutine調用立即返回。與函數不同,go不等待Goroutine執行結束。當Goroutine調用,并且Goroutine的任何返回值被忽略之后,go立即執行到下一行代碼。
  • main的Goroutine應該為其他的Goroutines執行。如果main的Goroutine終止了,程序將被終止,而其他Goroutine將不會運行。
  • 修改以上代碼:

    package main ? import ( "fmt""time" ) ? func hello() { fmt.Println("Hello world goroutine") } func main() { go hello()time.Sleep(1 * time.Second)fmt.Println("main function") }

    運行結果:

    在上面的程序中,我們已經調用了時間包的Sleep方法,它會在執行過程中睡覺。在這種情況下,main的goroutine被用來睡覺1秒?,F在調用go hello()有足夠的時間在main Goroutine終止之前執行。這個程序首先打印Hello world goroutine,等待1秒,然后打印main函數。

    1.4 啟動多個Goroutines

    示例代碼:

    package main ? import ( "fmt""time" ) ? func numbers() { for i := 1; i <= 5; i++ {time.Sleep(250 * time.Millisecond)fmt.Printf("%d ", i)} } func alphabets() { for i := 'a'; i <= 'e'; i++ {time.Sleep(400 * time.Millisecond)fmt.Printf("%c ", i)} } func main() { go numbers()go alphabets()time.Sleep(3000 * time.Millisecond)fmt.Println("main terminated") }

    運行結果:

    1 a 2 3 b 4 c 5 d e main terminated

    時間軸分析:

    總結

    以上是生活随笔為你收集整理的go 怎么等待所有的协程完成_GO语言基础进阶教程:Go语言的协程——Goroutine的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。