為了演示,我制作了一個程式,試圖說明如何使用 Go 制作一個并發并并行運行的程式。輸出似乎表明它至少是同時運行的,但我不確定如何判斷它是否是并行運行的。我已經閱讀了很多關于如何使用 goroutines 并將它們同步到 WaitGroup 的資源,但是對于它們是否在單獨的執行緒上運行似乎有很多困惑。作為一名剛接觸 Go 的新手程式員,我非常感謝您的澄清!
package main
import (
"fmt"
"sync"
"time"
)
//take order
func takeOrder1(wg *sync.WaitGroup) {
s_sleep(1000)
fmt.Println("\nTaking order...", t_time())
go takeOrder2(wg)
}
func takeOrder2(wg *sync.WaitGroup) {
s_sleep(1500)
fmt.Println("\nOrder tooken!", t_time())
wg.Done()
}
//make fires
func makeFries1(wg *sync.WaitGroup) {
s_sleep(1500)
fmt.Println("\nFrying fries...", t_time())
go makeFries2(wg)
}
func makeFries2(wg *sync.WaitGroup) {
s_sleep(3000)
fmt.Println("\nFries Fried!", t_time())
wg.Done()
}
//burn burger
func makeBurger1(wg *sync.WaitGroup) {
s_sleep(2000)
fmt.Println("\nFlipping burger...", t_time())
go makeBurger2(wg)
}
func makeBurger2(wg *sync.WaitGroup) {
s_sleep(5000)
fmt.Println("\nCooked a burger!", t_time())
wg.Done()
}
//cook drink
func pourDrink1(wg *sync.WaitGroup) {
s_sleep(1000)
fmt.Println("\nPutting ice in cup...", t_time())
go pourDrink2(wg)
}
func pourDrink2(wg *sync.WaitGroup) {
s_sleep(3000)
fmt.Println("\nPouring soda in cup...", t_time())
go pourDrink3(wg)
}
func pourDrink3(wg *sync.WaitGroup) {
s_sleep(2500)
fmt.Println("\nDrink poured!", t_time())
wg.Done()
}
//wipe table
func cleanTable1(wg *sync.WaitGroup) {
s_sleep(1000)
fmt.Println("\n'Cleaning' table....", t_time())
go cleanTable2(wg)
}
func cleanTable2(wg *sync.WaitGroup) {
s_sleep(1500)
fmt.Println("\nTable 'clean'!", t_time())
wg.Done()
}
//delay
func s_sleep(x int) { time.Sleep(time.Duration(x) * time.Millisecond) }
//just to print time
func t_time() string {
return time.Now().Format("15:04:05")
}
//create array of tasks to complete
var McDolansTasks = []func(*sync.WaitGroup){
takeOrder1, makeFries1, makeBurger1, pourDrink1, cleanTable1}
//main function
func main() {
var waitGroup sync.WaitGroup
// Set number of effective goroutines we want to wait upon
waitGroup.Add(len(McDolansTasks))
for _, task := range McDolansTasks {
// Pass reference to WaitGroup instance
// Each of the tasks should call on WaitGroup.Done()
go task(&waitGroup)
}
// Wait until all goroutines have completed execution.
waitGroup.Wait()
println("\nClock out for the day!")
}
( 
uj5u.com熱心網友回復:
簡短的回答是您不能顯示并發性和并行性,因為它們可能不是(并發和并行)。例如,如果你只有一個執行器——一個“P”,在內部 Go 運行時模型中——你一次只會運行一個 goroutine。
......關于這些是否在單獨的執行緒上運行似乎有很多困惑......
Go 一開始并不是根據“執行緒”來定義的,所以這個問題無法回答。這不是很令人滿意,但是除非您添加諸如“今天在我的系統上”之類的限定詞,否則就是您所得到的全部!所以也許你今天想在我的系統上添加限定符。
該規范允許goroutine 并行運行,并定義了 Go 的并發模型,但不需要任何特定的實作。這使得 Go 實作者可以自由地使用任何看起來合適的東西。我在上面提到了“內部 Go 運行時模型”,但沒有說是哪個. 我的意思是今天你系統上的那個。
公司目前旗下有一個主要執行的圍棋,雖然與實施的許多版本,根據需要為不同的CPU和圍棋的版本。那個實作有一個運行時(你可以在runtime包中呼叫一些在某種程度上控制它的東西),并且該運行時確實有一個內部模型。 在那個內部模型中,系統——作業系統和/或位于 Go 實作之下的其他實作——確實有執行緒。這些系統執行緒在內部稱為“M”:假定作業系統以一個執行緒啟動運行時m0,之后運行時將在合適的時候創建新的附加作業系統執行緒。
Povilas Versockas 有一篇(現在有點過時)關于 Go 運行時調度的文章。 這個問題的答案會在何時調度程式創建一個新的M和P?描述了一些其他功能。
請注意,術語行程和執行緒已經相當模糊,盡管對區別有一些普遍的共識。請參閱行程和執行緒有什么區別? 一個夠程是非常像一個執行緒,但在一般情況下,最現代化的執行緒系統分配一個“執行緒ID”給每個執行緒。Goroutines 特別沒有ID,這意味著無法與任何其他 goroutine 中的特定 goroutine 進行有意義的對話或討論。這有助于強制 Go 程式員使用通道進行通信。(它不能完全強制這樣做,但它確實有幫助。??)
要真正演示并行操作,您可以超越 Go 規范進入未定義行為的領域。每當行為是未定義的圍棋天賦,也可以通過別的定義,然后的東西,否則可能會允許你來證明并行。不幸的是,因為您已經超出了 Go 規范,所以您現在不再首先撰寫(可移植的)Go程式:您的演示只是演示了有關特定實作的一些內容。
您還可以使用除錯器,例如delve。除錯器通常必須以各種定義不佳的方式與運行時和作業系統互動,以便能夠向您展示程式中發生的事情,并且通過這樣做,他們傾向于展示各種未定義的-規范但實際上像這樣的行為。你不會得到任何關于這些的保證,除非它們是由(例如)你的作業系統提供的。但是你肯定看到了很多東西!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/358295.html
