什么时候用Goroutine?什么时候用Channel?

简介: 通过全局变量加锁同步来实现通讯,并不利于多个协程对全局变量的读写操作。加锁虽然可以解决goroutine对全局变量的抢占资源问题,但是影响性能,违背了原则。总结:为了解决上述的问题,我们可以引入channel,使用channel进行协程goroutine间的通信。

什么场景下用channel合适呢?


  1. 通过全局变量加锁同步来实现通讯,并不利于多个协程对全局变量的读写操作。
  2. 加锁虽然可以解决goroutine对全局变量的抢占资源问题,但是影响性能,违背了原则。
  3. 总结:为了解决上述的问题,我们可以引入channel,使用channel进行协程goroutine间的通信。


Go语言中的操作系统线程和goroutine的关系:


  1. 一个操作系统线程对应用户态多个goroutine。
  2. go程序可以同时使用多个操作系统线程。
  3. goroutine和OS线程是多对多的关系,即m:n。


Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信,引出了channel。


通道channel使用示例:


for range 从通道中取值,通道关闭时for range 退出


// 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)
   }
复制代码


channel升级,单通道,只读通道和只写通道


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)
}
复制代码


goroutine work pool,可以防止goroutine暴涨或者泄露


//使用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
   }
}
复制代码


goroutine使用select case多路复用,满足我们同时从多个通道接收值的需求


//使用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:
      }
   }
}()
复制代码


goroutine加锁 排它锁 读写锁


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()
}
复制代码


公众号:程序员升级打怪之旅

微信号:wangzhongyang1993

相关文章
|
15天前
|
Go
channel:goroutine间通信
【10月更文挑战第15天】
23 4
|
24天前
|
存储 安全 Go
探索Go语言的并发模型:Goroutine与Channel
在Go语言的多核处理器时代,传统并发模型已无法满足高效、低延迟的需求。本文深入探讨Go语言的并发处理机制,包括Goroutine的轻量级线程模型和Channel的通信机制,揭示它们如何共同构建出高效、简洁的并发程序。
|
16天前
|
存储 Go 调度
深入理解Go语言的并发模型:goroutine与channel
在这个快速变化的技术世界中,Go语言以其简洁的并发模型脱颖而出。本文将带你穿越Go语言的并发世界,探索goroutine的轻量级特性和channel的同步机制。摘要部分,我们将用一段对话来揭示Go并发模型的魔力,而不是传统的介绍性文字。
|
1月前
|
安全 Go 数据处理
掌握Go语言并发:从goroutine到channel
在Go语言的世界中,goroutine和channel是构建高效并发程序的基石。本文将带你一探Go语言并发机制的奥秘,从基础的goroutine创建到channel的同步通信,让你在并发编程的道路上更进一步。
|
5月前
|
安全 Go 调度
协程(goroutine)和通道(channel)是其并发模型
协程(goroutine)和通道(channel)是其并发模型
29 0
|
6月前
|
大数据 Go
goroutine
Goroutine 是 Go 语言中的一种轻量级线程,由 Go runtime 管理。它们非常轻量,创建和销毁的开销很小,同时它们之间的切换也非常高效。Goroutine 的使用可以极大地提高程序的并发性能,使得
36 3
goroutine+channel实现对多个goroutine的顺序执行
goroutine+channel实现对多个goroutine的顺序执行
|
Go 调度
一文初探 Goroutine 与 channel
哈喽大家好,我是陈明勇,本文介绍的内容是 Go 并发模块的两个重要角色 → goroutine 与 channel。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出!
12405 0
一文初探 Goroutine 与 channel
|
存储 Go
Golang中的管道(channel) 、goroutine与channel实现并发、单向管道、select多路复用以及goroutine panic处理
Golang中的管道(channel) 、goroutine与channel实现并发、单向管道、select多路复用以及goroutine panic处理
504 0
|
Go
何时使用Channel,何时使用Mutex ?
何时使用Channel,何时使用Mutex ?
115 0