標題:Channel 通道
日期:2022-06-29 14:39:00
toc:false
index_img:http://api.btstu.cn/sjbz/?lx=m_dongman&cid=7
類別:
- Go
標籤: - 解決
- 次數
- 指針
切記:不要通過共享內存通信,通過通信來共享內存
- 所有 channel 的發送操作都是阻塞的(又叫 block)
- 使用 waiteGroup 一定要配合指針使用
- 解決實際問題一定要基於並發不能保證有序或無序的情況去排查
直接上代碼,注意看註釋:
package main
import "fmt"
type worker struct {
in chan int
done chan bool
}
func main() {
const count = 4
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i)
}
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
for _, worker := range workers {
<-worker.done
<-worker.done
}
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
go func() { w.done <- true }() // 還可以建立有緩衝的通道來解決,這裡就和 done: make(chan bool, 1) 是一樣的效果,不再阻塞在這裡,結果無序
// w.done <- true
}
}
func createWorker(id int) worker {
w := worker{
in: make(chan int), // 加在 in 通道可以讓兩次數據都發送完,開啟了兩次 done 的接收,結果無序
done: make(chan bool), // 加在 done 通道可以讓第一次數據發送完,就直接開啟第二次數據發送,結果無序
}
go doWork(id, w)
return w
}
使用 sync.WaitGroup
實現:
package main
import (
"fmt"
"sync"
)
type worker struct {
in chan int
done *sync.WaitGroup
}
func main() {
const count = 4
var wg sync.WaitGroup
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(count * 2)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
w.done.Done()
}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: wg,
}
go doWork(id, w)
return w
}
將函數與 WaitGroup
一起使用:
package main
import (
"fmt"
"sync"
)
type worker struct {
in chan int
done func()
}
func main() {
const count = 4
var wg sync.WaitGroup
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(count * 2)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
w.done()
}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: wg.Done,
}
go doWork(id, w)
return w
}