go語言通道插入0 Go 語言的併發性

2021-10-14 09:58:09 字數 2116 閱讀 2495

昨天,我在 quora 上回答了乙個關於 go 語言併發模型的問題。現在,我覺得我還想再多說些什麼!併發性是 go 語言中最強大的特性之一。許多人討論了這個話題,從非常簡單到過於複雜的都有。今天,我也來說說我的看法。

go 語言的併發性是一種思維方式而不僅僅是乙個語法。為了利用 go 的強大功能,你需要首先了解 go 是如何實現**的併發執行。go 依賴於乙個叫做 csp(comminicating sequential process 通訊順序程序)的併發模型,在電腦科學中,它基本上是描述併發系統之間的互動模型。但是鑑於這不是一篇科學**,我會跳過那些繁瑣的過程直接介紹它的實際用途。

許多關於 go 的演講、演示和文獻在解釋 go 的併發性時都會用到如下短語:

聽起來真不錯。但是這到底是什麼意思呢?這花了我好一會兒的時間才理解這個概念。但是一旦我了解了這個概念,go 語言的程式設計對我來說就更加流暢了。albert einstein 曾經說過,如果你不能把它解釋得通俗易懂,那麼你就還沒有完全了解它。以下是我能想到的對於這句話的最簡單的解釋了。

那麼,go 語言是怎麼做到這個的呢? go 允許你傳送變數的值來給其他執行緒(實際上,這不是乙個實際意義上的執行緒,但是現在姑且可以這麼理解),來代替用鎖住變數的共享記憶體的方式。預設的行為是,傳送資料的執行緒和接收資料的執行緒都會等待直到資料到達它的目的地。執行緒的「等待」強制執行緒之間在交換資料時進行適當的同步。在你擼起袖子開始**設計之前,先想想併發性的這種實現方式。這樣你將會有更加穩定的軟體。

為了解釋得更清晰一點:是如何保證軟體的穩定呢?預設情況下,傳送執行緒和接收執行緒在完成值傳輸的過程中都不會執行任何操作。這意味著,在另乙個執行緒處理資料之前,其中乙個執行緒同時處理資料、出現競態等類似的問題的機會並不多。

不過還是要提醒大家,這個模型可能會被過度使用。你必須知道這何時應該使用它,或者何時恢復到良好的舊的共享記憶體模型。例如,引用計數最好在鎖中保護,檔案訪問也是如此。go 語言也會通過同步包來支援你使用鎖保護。

在 go 裡,'goroutine' 就是作為上面提到的所謂的執行緒。實際上,這並不能稱為執行緒,這只是乙個可以和其他 'goroutine' 併發地在同乙個位址空間上面的函式。它們在 o.s 執行緒中被多路復用,因此如果有乙個被阻塞了,其他的仍然可以繼續執行。所有的同步和記憶體管理都由 go 本地執行。之所以說它們不是真正的執行緒,是因為它們並不一定總是要並行執行。然而,由於多路復用和同步,你會得到併發的效果。要啟動乙個新的 'goroutine' ,你只需要使用關鍵字 "go" :

go processdatafunction()

「 go 通道」是 go 語言實現併發性的另乙個概念。這個通道是用於不同的 goroutine 之間的記憶體交流。要建立乙個通道,就要用到 "make" 關鍵字:

mychannel := make(chan int64)

mybufferedchannel := make(chan int64,4)

在上面的兩個例子中,我假設通道的變數沒有提前定義。這就是我為什麼使用 ":=" 來建立提及型別的變數而不是使用 "=", 因為 "=" 只會進行賦值,如果變數使用之前沒有宣告,就會導致編譯錯誤。

現在到了使用通道的時候了,捏可以使用 "<-" 符號。傳送該值的 goroutine 會將其分配給通道,如下所示 :

mychannel <- 54

另乙個 goroutine 接收到這個值,會將它從通道中取出來並且重新賦給乙個新的變數:

myvar := <- mychannel

現在讓我們看乙個例子來展示 golang 中的案例併發性:

package main

import (

"fmt"

"time"

)func main()

func sendinggoroutine(ch chan int)

func receivinggoroutine(ch chan int, done chan bool)

輸出:

sending a value on a channel

received value 45

go語言通道插入0 Go 語言通道

51reboot 運維開發 golang 課程 k8s 課程 python 自動化高階課程 python 基礎實戰課程 運維前端課程 課程試聽預約請掃碼 原子函式和互斥函式都能工作,但是依靠它們都不會讓編寫併發程式變得更簡單,更不容易出錯,或者更有趣。在 go 語言裡,你可以使用通道來傳送和接收需要...

go語言通道插入0 Go語言之通道

所以在多個goroutine併發中,我們不僅可以通過原子函式和互斥鎖保證對共享資源的安全訪問,消除競爭的狀態,還可以通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,它有點像在兩個routine之間架設的管道 乙個goroutine可以往這個管道裡塞資料,另外乙個...

go語言通道插入0 Go語言帶緩衝的通道

go語言中有緩衝的通道 bufferedchannel 是一種在被接收前能儲存乙個或者多個值的通道。這種型別的通道並不強制要求goroutine之間必須同時完成傳送和接收。通道會阻塞傳送和接收動作的條件也會不同。只有在通道中沒有要接收的值時,接收動作才會阻塞。只有在通道沒有可用緩衝區容納被傳送的值時...