linux 國外網(wǎng)站網(wǎng)站建設(shè)蘇州
什么協(xié)程
在Go語言中,協(xié)程就是一種輕量的線程,是并發(fā)編程的單元,由Go來管理,所以在GO層面的協(xié)程會更加的輕量、高效、開銷更小,并且更容易實現(xiàn)并發(fā)編程。
輕量級線程
- Go語言中協(xié)程(線程)與傳統(tǒng)系統(tǒng)層面的線程相比,實在是太輕量了,能小到2kb
- 由于協(xié)程的輕量特性,可以更高效地利用系統(tǒng)資源。相較于傳統(tǒng)的線程,協(xié)程的創(chuàng)建和銷毀的開銷更小,使得程序更具有擴展性和性能優(yōu)勢。
Go自身管理
- 在 Go 中,這些工作由運行時系統(tǒng)自動完成。這樣我們就可以更專注于業(yè)務(wù)邏輯,而不必過多關(guān)心底層線程管理的細節(jié)。
并發(fā)的基本單元
- 協(xié)程是并發(fā)編程的基本單元,可以同時執(zhí)行多個協(xié)程,而它們之間的調(diào)度和切換由運行時系統(tǒng)負責。
- 在程序中更容易實現(xiàn)高效的并發(fā),處理多個任務(wù)而無需顯式地創(chuàng)建和管理線程。
- 使用協(xié)程,我們可以輕松地實現(xiàn)并發(fā)任務(wù),例如同時處理多個網(wǎng)絡(luò)請求、執(zhí)行后臺任務(wù)等。由于協(xié)程的輕量特性,可以創(chuàng)建數(shù)千甚至數(shù)百萬個協(xié)程而不會造成系統(tǒng)負擔。
使用通道通信
- 協(xié)程之間可以通過通道進行通信,這是一種在協(xié)程之間安全地傳遞數(shù)據(jù)和同步操作的機制。通道是一種強大的工具,用于協(xié)程之間的協(xié)作和數(shù)據(jù)傳遞。
協(xié)程的基本操作
創(chuàng)建協(xié)程
- 語法: `go 函數(shù)(函數(shù)列表)`
package main import ( "fmt" "time") func Hello() { fmt.Println("hello world")
} func main() { go Hello() fmt.Println("hello main") time.Sleep(10 * time.Second)
}
協(xié)程與主線程是并發(fā)執(zhí)行的。
協(xié)程間通行
- 主要通過
channel
來實現(xiàn)的
package main import ( "fmt"
) func sendMessage(ch chan string, msg string) { ch <- msg
} func main() { messagechan := make(chan string) go sendMessage(messagechan, "Hello World") msg := <-messagechan fmt.Println(msg)
}
協(xié)程間的同步
- 使用sync包來實現(xiàn)的
- waitgroup 是用來計數(shù)信號量的
package main import ( "fmt" "sync") func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("worker %d starting\n", id) fmt.Printf("worker %d done\n", id)
} func main() { var wg sync.WaitGroup for i := 1; i <= 10; i++ { wg.Add(1) go worker(i, &wg) } wg.Wait() fmt.Printf("all workers done\n")
}
waitgroup確保主線程等待所有協(xié)程完成
協(xié)程的錯誤處理
- 使用
select
語句和通道可以實現(xiàn)協(xié)程的錯誤處理
package main import ( "fmt" "time") func dosomething(ch chan string) { time.Sleep(2 * time.Second) ch <- "hello world"
} func main() { ch := make(chan string) go dosomething(ch) select { case msg := <-ch: fmt.Println(msg) case <-time.After(1 * time.Second): fmt.Println("timeout") }
}
select
?語句允許在多個通道操作中選擇一個可用的操作,可以用來處理協(xié)程的超時等情況。
協(xié)程的高級操作
協(xié)程池
- 協(xié)程池是一組預(yù)先創(chuàng)建的協(xié)程,用于執(zhí)行并發(fā)任務(wù),可以避免頻繁創(chuàng)建和銷毀協(xié)程的開銷。
- 使用緩沖通道來實現(xiàn)協(xié)程池
package main import ( "fmt" "sync") func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("worker", id, "started job", j) results <- j * 2 }
} func main() { const numJobs = 5 const numWorkers = 3 jobs := make(chan int, numJobs) results := make(chan int, numJobs) var wg sync.WaitGroup for i := 1; i <= numWorkers; i++ { wg.Add(1) go func(i int) { defer wg.Done() worker(i, jobs, results) }(i) } for j := 1; j <= 5; j++ { jobs <- j } close(jobs) go func() { wg.Wait() close(results) }() for result := range results { fmt.Println("result", result) }
}
三個協(xié)程形成了協(xié)程池,從任務(wù)通道?
jobs
?中獲取任務(wù),處理后將結(jié)果發(fā)送到結(jié)果通道?results
超時控制
package main import ( "fmt" "time") func dosomething(ch chan string) { time.Sleep(2 * time.Second) ch <- "hello world"
} func main() { ch := make(chan string) go dosomething(ch) select { case msg := <-ch: fmt.Println(msg) case <-time.After(1 * time.Second): fmt.Println("timeout") }
}
time.After
?創(chuàng)建一個計時器,如果在指定時間內(nèi)沒有從通道?ch
?中接收到結(jié)果,就會觸發(fā)超時。
協(xié)程的取消
- 使用?
context
?包提供的上下文(Context)來實現(xiàn)協(xié)程的取消。
package main import ( "context" "fmt" "time") func doSomething(ctx context.Context, ch chan string) { select { case <-ctx.Done(): ch <- "task completed successfully" case <-time.After(1 * time.Second): ch <- "task timed out" }
} func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ch := make(chan string) go doSomething(ctx, ch) time.Sleep(2 * time.Second) cancel() result := <-ch fmt.Println(result)
}
通過調(diào)用?
cancel
?函數(shù)取消協(xié)程的執(zhí)行。