go學習 goroutine併發學習總結

2022-03-13 08:03:59 字數 3457 閱讀 1465

go最大的特性就是併發了,所以這一塊是go的重點知識,我自己花了一些時間,好好學習這個基礎知識。

文章內容為個人學習理解,所以文章如果有不對之處,非常感謝指出。

說起go併發,一般都會指go協程,即goroutine,而實現goroutin的關鍵字就是go

我學習go併發用到的關鍵字總結

sync.mutex // 鎖

sync.once // 只執行一次函式

sync.waitgroup // 等待所有協程執行完

runtime.numgoroutine() // 檢視當前執行的協程數量

package main

import (

"fmt"

"time"

)func main() ()

// sleep 1 秒的目的是為了 等待協執行完看到結果 不至於 主程式執行完了 協程還沒結束

time.sleep(1*time.second)

}

go裡面協程間可以使用channel進行通訊,不推薦直接使用變數互動資料,避免資料操作混亂。

協程資料相當於乙個 管道佇列機構 先進先出

無緩衝區時,必須同時讀取才行,否則會報錯fatal error: all goroutines are asleep - deadlock!

錯誤的例子

func main()
正確的例子

func main()()

n := <- c1

// 輸出1

fmt.println(n)

}

補充說明一下,當緩衝區還沒有資料進來時,讀取操作會被阻塞, 比如以下例子

func main()()

// 先輸出 ----

fmt.println("-----")

n := <- c1

// 等待5秒緩衝區有資料了 程式才會接著往下執行

fmt.println("+++++")

fmt.println(n)

}

func main()
上面的例子中,乙個個的寫入和讀取channel中的資料,特別麻煩,於是就有迴圈寫入和讀取。需要注意的是使用range迴圈讀取時,channel必須得用close來結束,

否則就回因為range無法判斷是否結束,而導致異常

func main()

// 結束新增

close(c)

}(cap(c), c)

// 迴圈取出

for v := range c

}

使用sync.waitgroup等待多個goroutine同時執行完,使用selectcase隨機執行返回值

// 兩個協程任務分別往不同的channel存入資料

func asyncch1(n int, c chan string, wg *sync.waitgroup)

// done() 結束時會把之前新增的協程數量減一

wg.done()

}func asyncch2(n int, c chan string, wg *sync.waitgroup)

wg.done()

}func main()

}}

模擬實現超時操作,把上面的例子改造一下,然後新增超時操作。

func asyncch1(n int, c chan string) 

// 去掉等待結束完成

}func asyncch2(n int, c chan string)

}func testselect(t *testing.t)

}}

如果是使用了close關閉chan,那麼channel取值其實是有兩個返回值的,相當於close發出了乙個訊號

v, ok := <-c;if ok  else
如下完整例子

// 不斷的生產

func producer1(c chan int, wg *sync.waitgroup)

// 關閉channel

close(c)

//c <- 22 // 關閉後就不能發了 panic: send on closed channel

wg.done()

}// 不斷的從chanel裡面拿

func consumer(c chan int, wg *sync.waitgroup) else

} wg.done()

}func main()

func producer5(writec chan<- int) 

}func consumer5(redc <-chan int)

}func main()

var once sync.once

func normalfunc(i int)

func singlefunc(i int) )

}func main() (i)

} wg.wait()

}

// 新建乙個空結構體 相當於物件

type tool struct

// 物件池 用於儲存 tool物件

type toolsbox struct

// 獲取工具 給結構體繫結方法

func (p *toolsbox) gettool(timeout time.duration) (*tool, error)

}// 用完歸還(釋放)

func (p *toolsbox) releasetool(tool *tool) error

}// new乙個 toolbox物件

func newtoolsbox(poolnum int) *toolsbox

objpool.bufchan = make(chan *tool, poolnum)

for i := 0; i < poolnum; i++

// 存入物件池

objpool.bufchan <- tool

} return &objpool

}func main() else else

} }t.log("結束")

}

github

Go語言 併發程式設計goroutine

在go語言中併發是通過goroutine實現。goroutine類似於執行緒,屬於使用者態執行緒。go語言也可以通過channel 管道 與多個goroutine進行通訊。goroutine類似於執行緒,在go語言中底層分配了乙個執行緒池,因此不需要我們對其進行管理,由go執行時的routine進行...

go 語言併發機制 goroutine 初探

go 語言的乙個很大的優勢就是可以方便地編寫併發程式。go 語言內建了 goroutine 機制。這是一種類似 coroutaine 協程 的東西。但是又不完全相同。比如這個例子 package main import fmt strconv func main func task name str...

Go併發模式之 防止goroutine洩漏

goroutine 有以下幾種方式被終止 1。當他完成了它的工作。2。因為不可恢復的錯誤,它不能繼續工作 3。當他被告知 需要終止工作。我們可以簡單的使用前兩種方法,因為這兩種方法隱含在你的演算法中,但 取消工作 又是怎樣工作的呢?例如 這樣情況 子goroutine 是否該繼續執行可能是以許多其他...