作者: BigLoser 访问次数: 227 创建时间: 2022-10-24 18:00:33 更新时间: 2024-04-26 15:51:04
通过全局变量加锁同步来实现通讯,并不利于多个协程对全局变量的读写操作。
加锁虽然可以解决 goroutine 对全局变量的抢占资源问题,但是影响性能,违背了原则。
总结:为了解决上述的问题,我们可以引入 channel,使用 channel 进行协程 goroutine 间的通信。
一个操作系统线程对应用户态多个 goroutine。
go 程序可以同时使用多个操作系统线程。
Goroutine 和 OS 线程是多对多的关系,即 m:n。
Go 语言的并发模型是 CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信,引出了 channel。
// channel练习 go for range从chan中取值 ch1 := make(chan int) ch2 := make(chan int) // 开启goroutine 把0-100写入到ch1通道中 go func() { for i := 0; i < 100; i++ { ch1 <- i } close(ch1) }() // 开启goroutine 从ch1中取值,值的平方赋值给 ch2 go func() { for { i,ok := <-ch1 //通道取值后 再取值 ok = false if ok { ch2 <- i*i }else { break } } close(ch2) }() // 主goroutine 从ch2中取值 打印输出 // for x := chan 有值取值,通道关闭时跳出goroutine for i :=range ch2{ fmt.Println(i) }
func counter(in chan<- int) { defer close(in) for i := 0; i < 100; i++ { in <- i } } func square(in chan<- int, out <-chan int) { defer close(in) for i := range out { in <- i * i } } func output(out <-chan int) { for i:=range out{ fmt.Println(i) } } // 改写成单向通道 func main() { ch1 := make(chan int) ch2 := make(chan int) go counter(ch1) go square(ch2, ch1) output(ch2) }
//使用work pool 防止goroutine的泄露和暴涨 func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker:%d start job:%d\n", id, j) time.Sleep(time.Second) fmt.Printf("worker:%d end job:%d\n", id, j) results <- j * 2 } } func main() { jobs := make(chan int, 100) results := make(chan int, 100) // 开启3个goroutine for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // 5个任务 for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // 输出结果 for a := 1; a <= 5; a++ { <-results } }
//使用select语句能提高代码的可读性。 //可处理一个或多个channel的发送/接收操作。 //如果多个case同时满足,select会随机选择一个。 //对于没有case的select{}会一直等待,可用于阻塞main函数。 ch := make(chan int, 1) go func() { for i := 0; i < 10; i++ { select { case x := <-ch: fmt.Println(x) case ch <- i: } } }()
var x int64 var wg sync.WaitGroup //添加互斥锁 var lock sync.Mutex func main() { wg.Add(2) go add() go add() wg.Wait() fmt.Println(x) } func add() { for i := 0; i < 5000; i++ { lock.Lock() //加锁 x = x + 1 lock.Unlock() //解锁 } wg.Done() }
语言: zh-CN
翻译人员:
原作者:
转载地址:
源网址: https://xie.infoq.cn/article/74e7d37a8401208231960e205
版权: 本站所有内容, 版权归原作者所有。发表原创内容将会获得现金奖励, 并且随着时间倍数增长, 请了解我们的内容奖励计划。