golang最擅長的就是併發程式設計,使用golang可以很方便的進行併發程式設計。先看一段普通的**
package main
import (
"f""time")
func foo(i int)
func main()
}輸出為0 will sleep
0 wake up
1 will sleep
1 wake up
2 will sleep
2 wake up
3 will sleep
3 wake up
4 will sleep
4 wake up
大概要執行25秒的時間,因為我們的foo中休眠5s,5次迴圈,去掉其他時間至少需要25秒時間執行完成。
現在,我們希望併發呼叫foo函式,很簡單,使用go關鍵字建立協程(協程比執行緒的執行更加輕量級)
package main
import (
"fmt"
"time"
) func foo(i int)
func main()
time.sleep(10 * time.second)
}在呼叫foo前使用了go,這樣就會併發執行,最後新增休眠10秒,是防止主程序結束,協程也被銷毀。
package main
import (
"fmt"
"time")
func foo(i int, ch chan int)
count := 0
for count < 5 {
count +=
通道屬於復合型別,我們使用make函式建立通道,通道型別是int,也就是我們可以使用該通道傳遞int型別的值。
我們在主函式中向foo函式傳遞通道作為引數,當foo函式執行結束後,通過通道傳送數字1(ch
當五個協程都執行結束後退出迴圈。使用通道,我們還可以實現生產者和消費者模式。
package main
import (
"fmt"
"math/rand")
func consumer(ch www.cppcns.com producer(ch)
go consumer(ch, result)
fmt.printf("result: %d\n",
我們在生產者和消費者之間使用ch通道傳遞資料,使用reslut通道給主函式返回結果。注意觀察consumer函式和producer函式的引數列表,這裡通道引數的傳遞略有不同,指明了通道的方向,chan
可以看到,go語言實現併發非常簡單,借用通道,又可以在不同的協程之間方便的傳輸資料。
補充:golang通道的定義
先上一段**,
func main() {
// 示例1
//通道是乙個先進先出(fifo)的佇列
channel := make(chan int,3)
channel
go 語言自帶的唯一乙個併發安全性的型別
定義:使用go的內建函式make, chan 是關鍵字, int是通道型別的資料,3是通道容量大小,不能小於0,如果為0,則表示非緩衝通道。
1. 通道中傳送操作是互斥的,接收操作也是互斥的,比如上面,往channel中傳送1,2,3,這發生再三個時刻,同一時刻你不可能傳送1同時傳送2,接收操作也是同樣的道理。
2. 傳送和接收操作對同乙個元素是原子性的,就是說上面市不可能往channe1中傳送1的同時又把1從channel取出來,只有1這個元素完整的複製進channel中時,你才可以取出1這個元素來
3程式設計客棧. 傳送操作在完成之前會被阻塞,接收操作也是同理,比如你把1往channel完完整整地複製進去通道,這需要時間,在這個時間內,channel
以上這三個性質,隱約的感覺到了,就是為了實現互斥同時保證元素的安全性
通道元素值移動的過程:比如把1傳送到channel中,首先元素1複製乙個副本傳送到通道,等到要取走時,通道的副本1再複製乙個副本2,給要取值的對方,等到對方完全取走後,通道裡的副本1才會被刪除。
func main() {
// 示例2
channel := make(chan int,3)
channel
發生在通道快取已滿,但還忘通道裡面傳送元素,比如注釋中的"報錯1"處,因為通道的容量就是3,你寫了1,2,3之後再往裡面寫這時就寫不進一直阻塞再那裡
傳送再通道快取已空,但是還想從通道中取值,比如注釋中的"報錯2"處,此時你已取走了1,2,3,你再取值時,已經為空就一直阻 塞再那裡
對於非緩衝通道,比如示例3,定義了乙個channel2通道,容量為0,程式執行到「channel2
func main() {
// 示例4
channel3 := make(chan int,2)
channel3 程式設計客棧
close(channel5)
v3,b3 :=
往乙個已經關閉了的通道裡面傳送值時會引發「panic」。比如上面注釋報錯3處,前面已執行「close(channel3)」關閉通道操作,再往裡面傳送值就會引發panic。
關閉乙個已經關閉的通道時,會引發「panic」。比如上面注釋「報錯4」處。
示例5和示例6的區別僅僅在於關閉通道後,裡面是否還有值剩餘?假設有剩餘,我們就可以從通道取值同時賦給兩個變數,第二個變數是bool型別值,其為true表示取到了值,其為false表示沒有取到值,這樣僅僅可以避免引發「panic」,如果通道已經關閉且無元素值,則取出的第二個bool值為false;若從已關閉的通道裡面(裡面無剩餘元素值)再次讀取元素值,則第二個值為true。
總結:第二個bool值為false,則通道肯定關閉了,值為true,可能關閉也可能沒有關閉
本文標題: golang 併發以及通道的使用方式
本文位址:
Golang併發以及通道的使用
golang最擅長的就是併發程式設計,使用golang可以很方便的進行併發程式設計。先看一段普通的 package main import fmt time func foo i int func main 輸出為 0 will sleep 0 wake up 1 will sleep 1 wake...
Golang併發 goroutine和通道
goroutine 和通道 channel 實現的通訊順序程序 csp 模式 共享記憶體多執行緒模式 goroutine goroutine指每乙個併發執行的活動。main函式在主goroutine中執行。goroutine通過go關鍵字建立。gof 新建乙個goroutine呼叫f go語句本身立...
Golang併發控制 context的使用
我們已經知道waitgroup可以用於併發控制,但當遇到更複雜的場景時,例如主動取消goroutine或者使超時的goroutine自動退出等,waitgroup就無能為力。這個時候,就是context大有用武之地。包context定義了context型別,它跨api邊界和程序之間攜帶截止日期,取消...