• go 通道的运用


    无缓冲通道:同步通道

    //对无缓冲channel类型的发送与接收操作,一定要放在两个不同的Goroutine中进行,否则会导致deadlock。
    //无缓冲通道,必须接收和发送都准备好了才能执行。否则会阻塞。
    //所以无缓冲通道相当于是同步通道了。
    var helloChan = make(chan struct{})
    
    func Test33() {
    	fmt.Println("数一下羊吧~~~")
    	go SaySheep()
    	<-helloChan //这里会暂时阻塞直到SaySheep遍历执行输出10只羊后收到helloChan通道发送的值才会继续下一步
    	fmt.Println("you are bad bad")
    }
    
    func SaySheep() {
    	for i := 0; i < 10; i++ {
    		fmt.Println("🐏")
    	}
    	helloChan <- struct{}{} //空结构体不占用内存
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    输出结果:
    在这里插入图片描述

    有缓冲通道:控制协程、并发的数量

    //利用有缓冲通道控制协程的数量,利用waitGroup控制协程的结束
    var wg sync.WaitGroup
    
    func Test35() {
    	//利用有缓冲通道控制协程数量为3
    	ch := make(chan struct{}, 3)
    	for i := 0; i < 20; i++ {
    		wg.Add(1)
    		//这里缓冲通道写满了3个数据后,就会阻塞,等待Weekend方法中发送通道里的数据,才能继续执行
    		ch <- struct{}{}
    		go Weekend(ch, i)
    	}
    	wg.Wait()
    }
    
    func Weekend(ch chan struct{}, i int) {
    	fmt.Println("周末拉", i)
    	fmt.Println(" goroutine count = ", runtime.NumGoroutine())
    	// time.Sleep(time.Duration(i) * time.Second)
    	<-ch
    	wg.Done()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    输出结果:
    在这里插入图片描述

    无缓冲通道也可以控制并发的数量

    //无缓冲通道控制协程数量
    //思想:开启固定的goroutine池,然后设置无缓冲的通道作为接收任务的中介,固定的协程读取到通道中任务就执行任务。
    var wg sync.WaitGroup
    
    func Test36() {
    	var cowChan = make(chan string)
    	var go_num = 3 //指定协程的数量为3
    	for i := 0; i < go_num; i++ {
    		go CallCowBoy(cowChan)
    	}
    	for i := 0; i < 20; i++ {
    		SendTask(cowChan, i)
    		//也可以直接写在这里
    		// wg.Add(1)
    		// cowChan <- "🐂🤠" + strconv.Itoa(i)
    	}
    	wg.Wait()
    }
    
    func CallCowBoy(ch chan string) {
    	for v := range ch {
    		fmt.Printf("%s are very busy \n", v)
    		fmt.Println(" goroutine count = ", runtime.NumGoroutine())
    		wg.Done()
    	}
    }
    
    func SendTask(ch chan string, i int) {
    	wg.Add(1)
    	ch <- "🐂🤠" + strconv.Itoa(i)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    Visual Studio Code 高效开发 C/C++ 插件推荐
    CSS3_媒体查询
    定时器的使用
    新建stm32工程——基于标准库也就是库函数的方式
    迈向100倍加速:全栈Transformer推理优化
    【PHP库】phpseclib - sftp远程文件操作
    【Java基础】方法
    光学动作捕捉系统构成
    js的promise的究竟是同步还是异步的问题和promise.all可以同时请求多个接口是错误的回答的原因
    AI大模型基础环境搭建
  • 原文地址:https://blog.csdn.net/weixin_38155824/article/details/125445693