title: Channel
date: 2022-06-29 14:39:00
toc: false
index_img: http://api.btstu.cn/sjbz/?lx=m_dongman&cid=7
category:
- Go
tags: - Solution
- Times
- Pointer
Remember: Do not communicate by sharing memory; instead, share memory by communicating.
- All send operations on channels are blocking (also known as blocking).
- When using waiteGroup, it must be used with a pointer.
- When solving practical problems, it is necessary to investigate based on concurrency and cannot guarantee order or disorder.
Let's go straight to the code, pay attention to the comments:
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 }() // A buffered channel can also be established to solve this problem. It has the same effect as done: make(chan bool, 1), and it will not block here anymore, resulting in unordered results.
// w.done <- true
}
}
func createWorker(id int) worker {
w := worker{
in: make(chan int), // Adding to the in channel allows both sets of data to be sent, opening two done receptions, resulting in unordered results.
done: make(chan bool), // Adding to the done channel allows the first set of data to be sent, and then directly opens the second set of data sending, resulting in unordered results.
}
go doWork(id, w)
return w
}
Implemented using 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
}
Using functions with 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
}