banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

通道

標題: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
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。