Go語言 多執行緒相關的一點思考

2021-10-05 18:43:38 字數 3572 閱讀 9451

go天生支援多執行緒,但是會有一些很有意思的事情值得思考

目錄

goroutine和系統執行緒

探索一:同時開啟兩個執行緒不加任何保護措施

探索二:去掉sleep直接執行

探索三:強行在main中新增sleep,完成實驗效果但是仍不安全

通道(channel)

通道緩衝區

go 遍歷通道與關閉通道

解決方法一:引入通道

解決方法二:sync.waitgroup 參考

系統執行緒:每乙個系統執行緒都有固定大小的棧(一般預設是2mb),棧主要用於儲存函式遞迴呼叫和區域性臨時變數。對於消耗很大的執行緒存在著爆棧的危險,但對於大部分消耗很小的執行緒又會造成巨大浪費。解決方法無非兩方面,降低或提高棧的大小,這兩種方法顯然無法在根本上解決問題。

開啟兩個執行緒,中間sleep100ms,出現執行緒未執行完畢,func main已經結束!

所以此次執行會不列印任何值程式執行結束!

將sleep去掉,兩個執行緒只能隨機執行部分後,func main已經執行結束!所以這次的結果會隨機列印一些step和index!也有可能任何都列印不出來main函式就已經結束!

package main

import (

"fmt"

)func say(index int)

}func main()

仍不安全的寫法,index=1時尚未執行完main結束,即使加上func main中加入sleep可以達到預期效果,但是治標不治本!

package main

import (

"fmt"

"time"

)func say(index int)

}func main()

要解決這個問題,先學習一些go特有的通道:

通道(channel)是用來傳遞資料的乙個資料結構。

通道可用於兩個 goroutine 之間通過傳遞乙個指定型別的值來同步執行和通訊。操作符用於指定通道的方向,傳送或接收。如果未指定方向,則為雙向通道。

ch 

v :=

// 並把值賦給 v

通道使用前必須先建立:

ch := make(chan int)
注意:預設情況下,通道是不帶緩衝區的。傳送端傳送資料,同時必須有接收端相應的接收資料。 

通道可以設定緩衝區,通過 make 的第二個引數指定緩衝區大小:

ch := make(chan int, 100)
帶緩衝區的通道允許傳送端的資料傳送和接收端的資料獲取處於非同步狀態,就是說傳送端傳送的資料可以放在緩衝區裡面,可以等待接收端去獲取資料,而不是立刻需要接收端去獲取資料。

不過由於緩衝區的大小是有限的,所以還是必須有接收端來接收資料的,否則緩衝區一滿,資料傳送端就無法再傳送資料了。

注意:如果通道不帶緩衝,傳送方會阻塞直到接收方從通道中接收了值。如果通道帶緩衝,傳送方則會阻塞直到傳送的值被拷貝到緩衝區內;如果緩衝區已滿,則意味著需要等待直到某個接收方獲取到乙個值。接收方在有值可以接收之前會一直阻塞

go 通過 range 關鍵字來實現遍歷讀取到的資料,類似於與陣列或切片。格式如下:

v, ok :=
如果通道接收不到資料後 ok 就為 false,這時通道就可以使用 close() 函式來關閉。

package main

import (

"fmt"

)func fibonacci(n int, c chan int)

close(c)

}func main()

}

執行輸出結果為:

011

2358

1321

34

引入乙個通道,預設情況下,通道的存訊息和取訊息都是阻塞的,在 goroutine 中執行完成後給通道乙個值 0,則主函式會一直等待通道中的值,一旦通道有值,主函式才會結束。

}//引入通道的寫法

func say2(index int, ch chan int)

// 通道訊息傳送之前會一直處於阻塞的狀態!

ch close(ch)

}func main()

sync包提供了基本的同步基元,如互斥鎖。除了once和waitgroup型別,大部分都是適用於低水平程式執行緒,高水平的同步使用channel通訊更好一些。

waitgroup用於等待一組執行緒的結束。父執行緒呼叫add方法來設定應等待的執行緒的數量。每個被等待的執行緒在結束時應呼叫done方法。同時,主線程裡可以呼叫wait方法阻塞至所有執行緒結束。

package main

import (

"fmt"

"os"

"sync"

// "time"

)// func firstfunc (index int)

// }

// func secondfunc (index int)

// }

func main()

}()// 定義匿名函式,建立gorountine

go func()

}()fmt.println("等待程式執行結束!")

wg.wait()

fmt.println("程式執行結束!")

《go語言實戰》

《go語言高階程式設計》

多執行緒的一點想法

一直被多種途徑告之多執行緒是個好東西,很好很好,一定要會。但是它到底是怎樣的?如何去用?卻一直不慎了解。最近通過解決c ui卡死這個問題,對多執行緒有了一點感覺。打個比喻吧。中秋快來了,你提著大包小包去趕車回家,這個時候你感覺負擔很大很累走不動,然後你請了兩個樵夫來幫你提東西,現在你輕鬆了。但是到了...

關於多執行緒的一點總結

昨天又在toplanguage上看到一些關於輕量級執行緒的討論,於是對其中很有用的一段話轉過來 記錄下來以供自己日後慢慢研究。下面是由red.gmail.com發表在toplanguage上的 1.process per connection thread per connection 這在連線數不...

關於多執行緒的一點感想

寫了這麼多年多執行緒程式,多執行緒到底是用來幹嘛的,可能這是個很白痴的問題,就我的親身經歷看開主要是因為一下兩點 1.提公升程式效率 2.使得程式可以非同步執行,乙個執行緒幹這個活,另乙個執行緒幹另乙個活 嚴格來說,感覺這還是為了提公升程式效率,因為cpu本身就是在不同執行緒之間切換的,兩個執行緒能...